Una vista personalizada bien diseñada es similar a cualquier otra clase bien diseñada. Encapsula un conjunto específico de funcionalidades en una interfaz simple, usa la CPU y la memoria de manera eficiente, etc. Además de ser una clase bien diseñada, una vista personalizada debe tener las siguientes características:
- Cumplir con los estándares de Android
- Proporcionar atributos con estilo personalizado que funcionen con diseños XML de Android
- Enviar eventos de accesibilidad
- Ser compatible con múltiples plataformas de Android
El marco de trabajo 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 analiza cómo usar el marco de trabajo de Android para crear la funcionalidad principal de una clase de vista.
Puedes encontrar información adicional en Componentes de vista personalizada.
Cómo crear una subclase para 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 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); } }
Cómo definir atributos personalizados
Para agregar una View integrada a la interfaz de usuario, debes especificarla en un elemento XML y controlar 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
<declare-styleable>elemento del recurso. - 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 en tu vista.
En esta sección, se analiza cómo definir atributos personalizados y especificar sus valores. En la siguiente sección, se trata la recuperación y la aplicación de los valores en el tiempo de ejecución.
Para definir atributos personalizados, agrega <declare-styleable>
recursos a tu proyecto. Es habitual colocar estos recursos en un
res/values/attrs.xml archivo. Este es
un ejemplo de un attrs.xml archivo:
<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 con estilo es, por convención, el mismo
nombre que el
nombre de la clase
que define la vista personalizada. Aunque no es necesario seguirla,
muchos editores de códigos
populares dependen de esta convención de nomenclatura para proporcionar la finalización de la declaración.
Una vez que hayas definido los atributos personalizados, podrás usarlos en archivos XML de diseño al igual que los atributos integrados. La única
diferencia es que tus 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, esta es la manera de 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
xmlns directiva. Esta directiva asigna el alias custom a
el espacio de nombres http://schemas.android.com/apk/res/com.example.customviews.
Puedes elegir cualquier alias que quieras para tu espacio de nombres.
Observa el nombre de la etiqueta XML que agrega la vista personalizada al diseño. Es el nombre completo de la clase de vista personalizada. Si tu clase de vista es una clase interna, debes calificarla
con el nombre de la clase externa de la vista.
Por ejemplo, la
PieChart clase tiene una clase interna denominada PieView. Para usar los
atributos personalizados de esta clase, debes
usar la etiqueta com.example.customviews.charting.PieChart$PieView.
Cómo aplicar atributos personalizados
Cuando se crea una vista desde un diseño XML, todos los atributos de la etiqueta XML se leen
del paquete de recursos
y se pasan al constructor de la vista como un
AttributeSet.
Aunque es posible leer valores directamente desde AttributeSet, esto tiene algunas desventajas:
- No se resuelven las referencias de recursos dentro de los valores del atributo.
- No se aplican estilos.
En su lugar, pasa el AttributeSet a
obtainStyledAttributes().
Este método muestra un
TypedArray
arreglo de
valores con
referencias resueltas y estilos aplicados.
El compilador de recursos de Android hace un gran trabajo para facilitar la llamada a
obtainStyledAttributes(). Para cada <declare-styleable>
recurso en el directorio res/, el R.java generado define tanto un arreglo de IDs de atributos como un conjunto de
constantes que definen el índice de cada atributo del arreglo. Las constantes predefinidas se usan para leer los atributos desde el TypedArray. Esta es la manera en que
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.
Cómo agregar propiedades y eventos
Los atributos son una forma eficaz de controlar el comportamiento y la apariencia de las vistas, pero
solo se pueden leer
si se inicializó la vista. Con el fin de proporcionar un comportamiento dinámico, expón un par de métodos get y set de propiedad para cada atributo personalizado. El siguiente fragmento muestra cómo PieChart expone una propiedad
llamada 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(); }
Observa que setShowText llama a invalidate()
y requestLayout(). Estas llamadas son cruciales
para garantizar que la vista se comportará de manera confiable. Debes
invalidar la vista después de cualquier cambio en las propiedades que pudiera modificar la
apariencia para que el
sistema sepa que deberá volver a generarla. Del mismo modo, si
cambia una propiedad que podría afectar el tamaño o la forma de la vista,
deberás solicitar un nuevo diseño. Si olvidas estas llamadas a métodos, se pueden generar errores difíciles de encontrar.
Las vistas personalizadas también deben permitir que los objetos de escucha de eventos comuniquen eventos importantes. Por
ejemplo, PieChart
expone un evento personalizado denominado 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 en detalle la interfaz de la vista, se reducirán los costos de mantenimiento futuros Una regla práctica es exponer siempre cualquier propiedad que afecte la apariencia visible o el comportamiento de la vista personalizada.
Diseño para la accesibilidad
La vista personalizada debe admitir una amplia variedad de usuarios, incluidos los que tienen 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
android:contentDescriptionatributo. - 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 hacer que las apps sean más accesibles.