O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Como criar uma classe de visualização

Uma visualização personalizada bem projetada é muito semelhante a qualquer outra classe bem projetada. Ele encapsula um conjunto específico de funcionalidades com uma interface fácil de usar, usa CPU e memória de forma eficiente e assim por diante. Porém, além de ser uma classe bem projetada, uma visualização personalizada precisa:

  • Estar em conformidade com 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.

Além desta lição, você pode encontrar mais informações sobre o assunto em Componentes personalizados.

Colocar visualização em subclasse

Todas as classes de visualização definidas no framework do Android estendem a View. Sua visualização personalizada também pode estender a View diretamente, ou você pode 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 pelo menos um construtor que aceite um objeto Context e um objeto 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 os atributos do elemento. Visualizações personalizadas bem escritas também podem ser adicionadas e estilizadas via XML. Para ativar esse comportamento na 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.
  • Recupere valores de atributo no momento da execução.
  • Aplique os valores do atributo recuperados à visualização.

Esta seção discute como definir atributos personalizados e especificar os valores deles. A próxima seção fala sobre como recuperar e aplicar os valores no tempo 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 dessa entidade é, por convenção, o mesmo nome da classe que define a visualização personalizada. Embora não seja estritamente 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 os atributos customizados, você pode usá-los nos 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/com.example.customviews">
     <com.example.customviews.charting.PieChart
         custom:showText="true"
         custom:labelPosition="left" />
    </LinearLayout>
    

Para evitar a repetição do URI de namespace longo, a amostra 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 completo da classe de visualização personalizada. Se sua 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 do AttributeSet diretamente, isso tem algumas desvantagens:

  • Referências de recursos dentro de valores de atributos não são resolvidas.
  • Estilos não são aplicados.

Em vez disso, passe o AttributeSet para obtainStyledAttributes(). Esse método retorna uma matriz TypedArray de valores que já tiveram a referência removida e foram 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 códigos de atributo e um conjunto de constantes que definem o índice para cada atributo na matriz. Use as constantes predefinidas para ler os atributos de 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();
       }
    }
    

Os 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 poderosa de controlar o comportamento e a aparência das visualizações, mas eles só podem ser lidos quando a visualização é inicializada. Para oferecer um 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. Invalide a visualização após qualquer alteração de propriedades que possa mudar a aparência dela para que o sistema saiba que precisa ser redesenhado. Da mesma forma, é necessário solicitar um novo layout se uma propriedade mudar, o que pode 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 os listeners de eventos para informar sobre eventos importantes. Por exemplo, o 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 parte.

É fácil esquecer de expor propriedades e eventos, especialmente quando você é o único usuário da visualização personalizada. Definir com atenção a interface da sua 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 ser compatível com 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 dar suporte a 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 adequado.
  • Ofereça compatibilidade com controles alternativos, como o botão direcional e o trackball.

Para mais informações sobre como criar visualizações acessíveis, consulte Como tornar os apps acessíveis no Guia do Desenvolvedor Android.