Uma visualização personalizada bem projetada é como qualquer outra classe bem projetada. Ele encapsula um conjunto específico de funcionalidades com uma interface simples, usa CPU e memória de forma eficiente e assim por diante. Além de ser uma classe bem projetada, uma visualização personalizada precisa fazer o seguinte:
- Seguir os padrões do Android.
- Fornecer atributos de estilo personalizados que funcionem com layouts XML do Android.
- Enviar eventos de acessibilidade.
- Ser compatível com várias plataformas Android.
O framework do Android oferece um conjunto de classes base e tags XML para ajudar a criar uma visualização que atenda a todos esses requisitos. Esta lição discute como usar o framework do Android para criar a funcionalidade principal de uma classe de visualização.
Você pode encontrar mais informações em Componentes de visualização personalizados.
Criar uma subclasse de uma visualização
Todas as classes de visualização definidas no framework do Android estendem
View
. A
visualização personalizada também pode
estender View
diretamente. Também é possível
economizar tempo estendendo uma das
subclasses de visualização
existentes, como Button
.
Para permitir que o Android Studio interaja com sua visualização, forneça no mínimo um construtor que use um objeto
Context
e AttributeSet
como parâmetros.
Esse construtor permite que o editor de layout crie e edite uma instância da sua visualização.
Kotlin
class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)
Java
class PieChart extends View { public PieChart(Context context, AttributeSet attrs) { super(context, attrs); } }
Definir atributos personalizados
Para adicionar uma View
integrada à interface do usuário, especifique-a em um elemento XML e
controle a
aparência e o comportamento dela com atributos do elemento. Você também pode adicionar e estilizar
visualizações personalizadas usando XML. Para
ativar esse comportamento na sua visualização personalizada, faça o seguinte:
- Defina atributos personalizados para sua visualização em um elemento de recurso
<declare-styleable>
. - Especifique valores para os atributos no seu layout XML.
- Recuperar valores de atributo no momento da execução.
- Aplique os valores do atributo recuperados à sua visualização.
Esta seção discute como definir atributos personalizados e especificar os valores deles. A próxima seção aborda a recuperação e a aplicação dos valores no ambiente de execução.
Para definir atributos personalizados, adicione recursos <declare-styleable>
ao seu projeto. É comum colocar esses recursos em um
arquivo res/values/attrs.xml
. Veja
um exemplo de um arquivo 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>
Esse código declara dois atributos personalizados, showText
e labelPosition
, que pertencem a uma entidade estilizável chamada PieChart
. O nome da entidade estilizável é, por convenção, o mesmo nome da classe que define a visualização personalizada. Embora não seja necessário seguir essa convenção, muitos editores de código conhecidos dependem dessa convenção de nomenclatura para fornecer a conclusão da instrução.
Depois de definir atributos personalizados, você pode usá-los em arquivos XML de layout, assim como os atributos
integrados. A única diferença é que seus atributos personalizados pertencem a um namespace diferente. Em vez de pertencer ao namespace http://schemas.android.com/apk/res/android
, eles pertencem a http://schemas.android.com/apk/res/[your package name]
. Por exemplo, veja como usar os
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 a repetição do URI do namespace longo, o exemplo usa uma
diretiva xmlns
. Essa diretiva atribui o alias custom
ao
namespace http://schemas.android.com/apk/res/com.example.customviews
.
Você pode escolher qualquer alias que quiser para seu namespace.
Observe o nome da tag XML que adiciona a visualização personalizada ao layout. É o nome totalmente qualificado da classe de visualização personalizada. Se a classe de visualização for interna, qualifique-a ainda mais com o nome da classe externa da visualização.
Por exemplo, a
classe PieChart
tem uma classe interna chamada PieView
. Para usar os atributos personalizados dessa classe, use a tag com.example.customviews.charting.PieChart$PieView
.
Aplicar atributos personalizados
Quando uma visualização é criada a partir de um layout XML, todos os atributos na tag XML são lidos
do pacote de recursos
e transmitidos para o construtor da visualização como um
AttributeSet
.
Embora seja possível ler valores diretamente no AttributeSet
, isso tem algumas desvantagens:
- As referências de recursos dentro de valores de atributo não são resolvidas.
- Os estilos não são aplicados.
Em vez disso, transmita AttributeSet
para
obtainStyledAttributes()
.
Esse método transmite de volta uma matriz TypedArray
de valores que já foram desreferenciados e estilizados.
O compilador de recursos do Android trabalha muito para facilitar a chamada de
obtainStyledAttributes()
. Para cada recurso <declare-styleable>
no diretório res/
, o R.java
gerado define uma matriz de IDs de
atributos e um conjunto de
constantes que definem o índice para cada atributo na matriz. Use as constantes predefinidas para ler os atributos do TypedArray
. Veja como a classe PieChart
lê 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(); } }
Observe que objetos TypedArray
são um recurso compartilhado
e precisam ser reciclados após o uso.
Adicionar propriedades e eventos
Os atributos são uma maneira eficiente de controlar o comportamento e a aparência das visualizações, mas eles só podem ser lidos quando a visualização é inicializada. Para fornecer comportamento dinâmico, exponha um par de getter e
setter de propriedade para cada
atributo personalizado. O snippet a seguir mostra como PieChart
expõe uma propriedade
chamada 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(); }
Observe que setShowText
chama invalidate()
e requestLayout()
. Essas chamadas são cruciais para garantir que a visualização se comporte de maneira confiável. É necessário invalidar a visualização após qualquer mudança nas propriedades que possa mudar a aparência dela, para que o sistema saiba que ela precisa ser redesenhada. Da mesma forma, você precisará solicitar um novo layout se uma propriedade mudar de maneira que possa afetar o tamanho ou a forma da visualização. Esquecer essas chamadas de método pode causar bugs difíceis de encontrar.
As visualizações personalizadas também precisam ser compatíveis com listeners de eventos para comunicar eventos importantes. Por exemplo, PieChart
expõe um evento personalizado chamado OnCurrentItemChanged
para notificar os listeners de que o usuário girou o gráfico de pizza para se concentrar em uma nova fração.
É fácil esquecer de expor propriedades e eventos, especialmente quando você é o único usuário da visualização personalizada. Definir com cuidado a interface da visualização reduz futuros custos de manutenção. Uma boa regra a seguir é sempre expor qualquer propriedade que afete a aparência ou o comportamento visível da visualização personalizada.
Design para acessibilidade
Sua visualização personalizada precisa oferecer suporte a uma grande variedade de usuários. Isso inclui usuários com deficiências que os impedem de ver ou usar uma tela sensível ao toque. Para ajudar usuários com deficiências, faça o seguinte:
- Rotule seus campos de entrada usando o atributo
android:contentDescription
. - Envie eventos de acessibilidade chamando
sendAccessibilityEvent()
quando apropriado. - Ofereça suporte a controles alternativos, como botão direcional ou trackball.
Para saber mais sobre como criar visualizações acessíveis, consulte Tornar os apps mais acessíveis.