Crea una clase de vista

Prueba el método 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 personalizados 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 marco de trabajo de Android para crear la funcionalidad principal de una clase de vista.

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

Crea una subclase para una vista

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

Para permitir que Android Studio interactúe con tu vista, como mínimo, debes proporcionar un constructor que tome un 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);
    }
}

Define atributos personalizados

Para agregar un View integrado a tu interfaz de usuario, especifícalo en un elemento XML y controla su apariencia y comportamiento con los atributos del elemento. También puedes agregar y diseñar vistas personalizadas 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 tiempo 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 durante el tiempo 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 estilo llamada PieChart. El nombre de la entidad que admite estilo es, por convención, el mismo nombre 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 instrucciones.

Una vez que defines los atributos personalizados, puedes usarlos en archivos en formato XML de diseño al igual que 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, a continuación, 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 vistas personalizadas. 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 denominada PieView. Para usar los atributos personalizados de esta clase, debes usar la etiqueta com.example.customviews.charting.PieChart$PieView.

Aplica atributos personalizados

Cuando se crea una vista desde 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. Si bien es posible leer valores de AttributeSet directamente, esta opción tiene algunas desventajas:

  • No se resuelven las referencias de recursos dentro de los valores de atributos.
  • Los estilos no se aplican.

En su lugar, pasa el AttributeSet a obtainStyledAttributes(). Este método devuelve un array de valores TypedArray con referencias resueltas y estilos aplicados.

El compilador de recursos de Android hace un gran trabajo para facilitar la llamada a obtainStyledAttributes(). Para cada recurso <declare-styleable> en el 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 manera eficaz de controlar el comportamiento y la apariencia de las vistas, pero solo se pueden leer cuando se inicializa la vista. Para proporcionar un comportamiento dinámico, expón un par de captador y método set 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 cruciales para garantizar que la vista se comporte de manera confiable. Debes invalidar la vista después de cualquier cambio en las propiedades que pueda modificar la apariencia para que el sistema sepa que debe volver a dibujarse. Del mismo modo, debes solicitar un diseño nuevo si una propiedad cambia de una manera que podría afectar el tamaño o la forma de la vista. Si olvidas estas llamadas a métodos, se pueden 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 una nueva porción 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 reducen los costos de mantenimiento futuros. Una buena regla a seguir es siempre exponer cualquier propiedad que afecte la apariencia visible o el comportamiento de tu vista personalizada.

Diseño para la accesibilidad

Tu vista personalizada debe admitir una amplia variedad de usuarios. Esto 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 tus 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.