Crea una clase de vista

Prueba el estilo de Compose
Jetpack Compose es el kit de herramientas de IU recomendado para Android. Obtén información para trabajar con diseños en Compose.

Una vista personalizada bien diseñada es como cualquier otra clase bien diseñada. Encapsula un conjunto específico de funciones con una interfaz simple, usa la CPU y la memoria de manera eficiente, etcétera. Además de ser una clase bien diseñada, una vista personalizada debe hacer lo siguiente:

  • Cumplen con los estándares de Android.
  • Proporciona atributos con estilo personalizado que funcionen con diseños XML de Android.
  • Envía eventos de accesibilidad.
  • Ser compatible con múltiples plataformas de Android

El framework de Android proporciona un conjunto de clases base y etiquetas XML para ayudarte a crear una vista que cumpla con todos estos requisitos. En esta lección, se explica cómo usar el framework de Android para crear la funcionalidad principal de una clase de vista.

Puedes encontrar información adicional en Componentes de vistas personalizadas.

Cómo crear una subclase de una vista

Todas las clases de vista definidas en el marco de trabajo de Android extienden View. Tu vista personalizada también puede extender View directamente, o puedes ahorrar tiempo extendiendo una de las subclases de vistas existentes, como Button.

Para permitir que Android Studio interactúe con tu vista, como mínimo, debes proporcionar un constructor que tome un objeto Context y un objeto AttributeSet como parámetros. Este constructor permite que el editor de diseño cree y edite una instancia de tu vista.

Kotlin

class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)

Java

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

Cómo definir atributos personalizados

Para agregar un View integrado a la interfaz de usuario, especifícalo en un elemento XML y controla su apariencia y comportamiento con los atributos del elemento. También puedes agregar vistas personalizadas y aplicar ajustes de diseño con XML. Para habilitar este comportamiento en tu vista personalizada, haz lo siguiente:

  • Define atributos personalizados para tu vista en un elemento del recurso <declare-styleable> .
  • Especifica valores para los atributos en tu diseño XML.
  • Recupera valores de atributos en el entorno de ejecución.
  • Aplica los valores de atributo recuperados a tu vista.

En esta sección, se analiza cómo definir atributos personalizados y especificar sus valores. En la siguiente sección, se explica cómo recuperar y aplicar los valores en el entorno de ejecución.

Para definir atributos personalizados, agrega recursos <declare-styleable> a tu proyecto. Es común colocar estos recursos en un archivo res/values/attrs.xml. Este es un ejemplo de un archivo attrs.xml:

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

En este código, se declaran dos atributos personalizados, showText y labelPosition, que pertenecen a una entidad con diseño llamada PieChart. Por convención, el nombre de la entidad con diseño es el mismo que el de la clase que define la vista personalizada. Aunque no es necesario seguir esta convención, muchos editores de código populares dependen de esta convención para completar las declaraciones.

Una vez que definas los atributos personalizados, podrás usarlos en archivos de diseño XML como los atributos integrados. La única diferencia es que los atributos personalizados pertenecen a un espacio de nombres diferente. En lugar de pertenecer al espacio de nombres http://schemas.android.com/apk/res/android, pertenecen a http://schemas.android.com/apk/res/[your package name]. Por ejemplo, aquí se muestra cómo usar los atributos definidos para PieChart:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res-auto">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

Para evitar tener que repetir el URI de espacio de nombres largo, en el ejemplo, se usa una directiva xmlns. Esta directiva asigna el alias custom al espacio de nombres http://schemas.android.com/apk/res/com.example.customviews. Puedes elegir cualquier alias que desees para tu espacio de nombres.

Observa el nombre de la etiqueta XML que agrega la vista personalizada al diseño. Es el nombre completamente calificado de la clase de vista personalizada. Si tu clase de vista es una clase interna, califícala con el nombre de la clase externa de la vista. Por ejemplo, la clase PieChart tiene una clase interna llamada PieView. Para usar los atributos personalizados de esta clase, usa la etiqueta com.example.customviews.charting.PieChart$PieView.

Aplica atributos personalizados

Cuando se crea una vista a partir de un diseño XML, todos los atributos de la etiqueta XML se leen desde el paquete de recursos y se pasan al constructor de la vista como un AttributeSet. Aunque es posible leer valores de AttributeSet directamente, esta opción tiene algunas desventajas:

  • No se resuelven las referencias a recursos dentro de los valores de los atributos.
  • No se aplican los diseños.

En su lugar, pasa el AttributeSet a obtainStyledAttributes(). Este método devuelve un array de valores TypedArray que ya tiene referencias y estilos diferentes.

El compilador de recursos de Android hace un gran trabajo para facilitar la llamada a obtainStyledAttributes(). Para cada recurso <declare-styleable> del directorio res/, el R.java generado define un array de IDs de atributos y un conjunto de constantes que definen el índice de cada atributo del array. Las constantes predefinidas se usan para leer los atributos desde TypedArray. A continuación, se muestra cómo la clase PieChart lee sus atributos:

Kotlin

init {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0).apply {

        try {
            mShowText = getBoolean(R.styleable.PieChart_showText, false)
            textPos = getInteger(R.styleable.PieChart_labelPosition, 0)
        } finally {
            recycle()
        }
    }
}

Java

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

Ten en cuenta que los objetos TypedArray son un recurso compartido y se deben reciclar después del uso.

Agrega propiedades y eventos

Los atributos son una forma eficaz de controlar el comportamiento y el aspecto de las vistas, pero solo se pueden leer cuando se inicializa la vista. Para proporcionar un comportamiento dinámico, expón un par de métodos get y set de propiedades para cada atributo personalizado. En el siguiente fragmento, se muestra cómo PieChart expone una propiedad denominada showText:

Kotlin

fun isShowText(): Boolean {
    return mShowText
}

fun setShowText(showText: Boolean) {
    mShowText = showText
    invalidate()
    requestLayout()
}

Java

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

Ten en cuenta que setShowText llama a invalidate() y requestLayout(). Estas llamadas son fundamentales para garantizar que la vista se comporte de manera confiable. Debes invalidar la vista después de cualquier cambio en sus propiedades que podría modificar su apariencia, de modo que el sistema sepa que se debe volver a dibujar. Del mismo modo, debes solicitar un nuevo diseño si una propiedad cambia de una manera que podría afectar el tamaño o la forma de la vista. Olvidar estas llamadas de método puede generar errores difíciles de encontrar.

Las vistas personalizadas también deben admitir objetos de escucha de eventos para comunicar eventos importantes. Por ejemplo, PieChart expone un evento personalizado llamado OnCurrentItemChanged para notificar a los objetos de escucha que el usuario rotó el gráfico circular para enfocarse en un nuevo sector circular.

Es fácil olvidarse de exponer propiedades y eventos, en especial cuando eres el único usuario de la vista personalizada. Si te tomas el tiempo para definir con cuidado la interfaz de la vista, se reducirán los costos de mantenimiento futuros. Una regla recomendada es exponer siempre cualquier propiedad que afecte la apariencia o el comportamiento visible de la vista personalizada.

Diseña para la accesibilidad

Tu vista personalizada debe admitir una amplia variedad de usuarios. lo que incluye a los usuarios con discapacidades que les impiden ver o usar una pantalla táctil. Para admitir usuarios con discapacidades, haz lo siguiente:

  • Etiqueta los campos de entrada con el atributo android:contentDescription.
  • Envía eventos de accesibilidad llamando a sendAccessibilityEvent() cuando corresponda.
  • Admite controles alternativos, como un pad direccional o una bola de seguimiento.

Para obtener más información sobre cómo crear vistas accesibles, consulta Cómo mejorar la accesibilidad de las apps.