lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Eventos de entrada

No Android, há mais de uma maneira de interceptar os eventos da interação de um usuário com o aplicativo. Ao considerar os eventos dentro da interface do usuário, a abordagem é capturar os eventos de um objeto de View específico com o qual o usuário interage. A classe View fornece os meios para fazer isso.

Dentro das várias classes View que você usará para compor o layout, é possível notar vários métodos públicos de retorno de chamada que parecem úteis para eventos de IU. Esses métodos são chamados pela estrutura de trabalho do Android quando a ação respectiva ocorre neste objeto. Por exemplo, quando uma View (como um botão) é tocada, o método onTouchEvent() é chamado neste objeto. No entanto, para interceptar isso, você deve estender a classe e substituir o método. No entanto, estender todos os objetos de View para lidar com tal evento não seria algo prático. É por isso que a classe View também contém uma coleção de interfaces aninhadas com retornos de chamada que podem ser definidas com muito mais facilidade. Essas interfaces, chamadas de escutas de evento, são sua passagem para capturar a interação do usuário com a IU.

Geralmente, os ouvintes de evento são usados para ouvir a interação do usuário. No entanto, há casos em que você pode querer estender uma classe View para criar um componente personalizado. Talvez você queira estender a classe Button para sofisticar alguma coisa. Neste caso, você poderá definir os comportamentos de evento padrão para a classe usando manipuladores de evento.

Escutas de evento

Um ouvinte de eventos é uma interface na classe View que contém um único método de retorno de chamada. Esses métodos serão chamados pela estrutura do Android, quando a View para a qual a escuta estiver registrada for ativada pela interação do usuário com o item na IU.

Inclusos nas interfaces da escuta de evento estão os seguintes métodos de retorno de chamada:

onClick()
De View.OnClickListener. Isso é chamado quando o usuário toca no item (no modo de toque) ou atribui foco ao item com as teclas de navegação ou o trackball e pressiona a tecla "enter" ou o pressiona o trackball.
onLongClick()
De View.OnLongClickListener. Isso é chamado quando o usuário mantém o item pressionado (no modo de toque) ou atribui foco ao item com as teclas de navegação ou o trackball e mantém pressionada a tecla "enter" ou o trackball (por um segundo).
onFocusChange()
De View.OnFocusChangeListener. Isso é chamado quando o usuário navega para ou do item usando as teclas de navegação ou o cursor de bola.
onKey()
De View.OnKeyListener. Isso é chamado quando o usuário está com foco no item ou solta uma tecla de hardware no dispositivo.
onTouch()
De View.OnTouchListener. Isso é chamado quando o usuário realiza uma ação qualificada como um toque de evento, incluindo o pressionamento, a liberação ou qualquer outro gesto de movimento na tela (dentro dos limites do item).
onCreateContextMenu()
De View.OnCreateContextMenuListener. Isso é chamado quando um menu de contexto está sendo construído (como resultado de um "clique longo"). Consulte a discussão sobre menus de contexto no guia do desenvolvedor de Menus .

Esses métodos são os únicos habitantes das respectivas interfaces. Para definir um desses métodos e lidar com seus eventos, implemente a interface aninhada na atividade ou defina-a como uma classe anônima. Em seguida, passe uma instância da implementação para o respectivo método View.set...Listener(). (Por exemplo, chame setOnClickListener() e passe-o à implementação de OnClickListener.)

O exemplo abaixo mostra como registrar uma escuta de clique para um botão.

// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(mCorkyListener);
    ...
}

Você também pode achar mais conveniente implementar OnClickListener como parte da atividade. Isso evitará carga adicional na classe e a alocação do objeto. Por exemplo:

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

Observe que o retorno de chamada onClick() no exemplo acima não tem valor de retorno, mas outros métodos de escuta de evento podem retornar um booleano. O motivo depende do evento. Para os poucos que retornam, eis o motivo:

  • onLongClick() - Isso retorna um booleano para indicar se você consumiu o evento e se ele não deve ser levado adiante. Ou seja, retorne verdadeiro para indicar que você processou o evento e ele não deve seguir adiante; ou retorne falso caso você não tenha processado o evento ou ele deva continuar para qualquer outro ouvinte de on-click.
  • onKey() - Isso retorna um booleano para indicar se você consumiu o evento e se ele não deve ser levado adiante. Ou seja, retorne verdadeiro para indicar que você processou o evento e ele não deve seguir adiante; ou retorne falso caso você não tenha processado o evento ou ele deva continuar para qualquer outro ouvinte de on-key.
  • onTouch() - Isso retorna um booleano para indicar se o ouvinte consome esse evento. O importante é que esse evento pode ter várias ações que seguem umas às outras. Portanto, se retornar falso quando o evento de ação inferior for recebido, você indicará que não consumiu o evento e que não está interessado em ações subsequentes deste evento. Logo, você não será chamado para outras ações dentro do evento, como um gesto de dedo ou um evento de ação para cima eventual.

Lembre-se de que os eventos de tecla de hardware sempre são entregues à exibição atualmente em foco. Eles são enviados a partir da parte superior da hierarquia de exibições e segue à parte inferior até atingir o destino adequado. Se a exibição (ou um filho da exibição) estiver em foco, é possível ver o percurso do evento pelo método dispatchKeyEvent(). Como alternativa para capturar eventos importantes na View, também é possível receber todos os eventos dentro da Activity usando onKeyDown() e onKeyUp().

Além disso, ao pensar sobre a entrada de texto para o aplicativo, lembre-se de que vários dispositivos têm apenas métodos de entrada de software. Tais métodos não precisam ser baseados em teclas; alguns podem usar entrada de texto por voz, por escrita e outros. Mesmo se um método de entrada apresentar uma interface parecida com teclado, geralmente ele não ativa a família de eventos onKeyDown(). Nunca se deve compilar uma IU que exija pressionamentos de teclas específicas para ser controlada, a não ser que você queira limitar o aplicativo a dispositivos com um teclado físico. Em particular, não confie nesses métodos para validar a entrada quando o usuário pressiona a tecla de retorno; em vez disso, use ações como IME_ACTION_DONE para sinalizar ao método de entrada como o aplicativo espera reagir para que ele possa alterar a IU de forma significativa. Evite suposições sobre como um método de entrada de software deve funcionar e confie apenas no fornecimento do texto já formatado para o aplicativo.

Observação: O Android chamará manipuladores de evento e, em seguida, manipuladores adequados padrão da segunda definição de classe. Logo, retornar verdadeiro destas escutas de evento interromperá a propagação do evento para outras escutas de evento e também bloqueará o retorno de chamada para o manipulador de evento padrão na exibição. Portanto, certifique-se de que quer encerrar o evento ao retornar verdadeiro.

Manipuladores de evento

Se estiver compilando um componente personalizado a partir de View, você poderá definir vários métodos de retorno de chamada usados como manipuladores de evento padrão. No documento sobre Componentes personalizados, você aprenderá a ver alguns dos retornos de chamada usados para lidar com eventos, incluindo:

Há alguns outros métodos de que você deve conhecer que não fazem parte da classe View, mas podem ter impacto direto na maneira de processar os eventos. Portanto, ao gerenciar eventos mais complexos dentro de um layout, considere esses outros métodos:

Modo de toque

Quando um usuário está navegando em uma interface do usuário com teclas direcionais ou cursor de bola, é necessário fornecer foco para itens de ação (como botões) para que o usuário possa ver o que aceitará entrada. Se o dispositivo tiver capacidades de toque, no entanto, e o usuário começar a interagir com a interface por meio de toque, não será mais necessário destacar itens nem fornecer foco para uma exibição específica. Contudo, há um modo de interação chamado "modo de toque".

Para dispositivos com capacidades de toque, quando o usuário toca na tela, o dispositivo entra no modo de toque. A partir desse ponto, somente exibições que tiverem isFocusableInTouchMode() como verdadeiro poderão ter foco, como widgets de edição de texto. Outras exibições tocáveis, como botões, não receberão foco ao serem tocadas. Em vez disso, elas simplesmente dispararão escutas de clique quando forem pressionadas.

Sempre que um usuário pressionar teclas direcionais ou rolar com o cursor de bola, o dispositivo sairá do modo de toque e encontrará uma exibição para atribuir foco. Agora, o usuário pode retomar a interação com a interface do usuário sem tocar na tela.

O estado de modo de toque é mantido em todo o sistema (em todas as janelas e atividades). Para consultar o estado atual, é possível chamar isInTouchMode() para ver se o dispositivo está no modo de toque no momento.

Processamento de foco

A estrutura lidará com a rotina de movimento de foco em resposta à entrada do usuário. Isso inclui a mudança de foco à medida que as exibições são removidas ou ocultadas, ou à medida que novas exibições se tornem disponíveis. As exibições indicam a prontidão para receber foco por meio do método isFocusable(). Para determinar se uma exibição pode receber foco, chame setFocusable(). Quando no modo de toque, é possível consultar se uma exibição permite foco com isFocusableInTouchMode(). É possível alterar isso com setFocusableInTouchMode().

O movimento de foco é baseado em um algoritmo que encontra um semelhante mais próximo em uma dada direção. Em casos raros, o algoritmo padrão pode não corresponder ao comportamento pretendido do desenvolvedor. Nessas situações, é possível fornecer modificações explícitas com os seguintes atributos XML no arquivo do layout: nextFocusDown, nextFocusLeft, nextFocusRight e nextFocusUp. Adicione um desses atributos à exibição a partir do foco que ela está abandonando. Defina o valor do atributo para ser o ID da exibição para o foco que deve ser fornecido. Por exemplo:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

Geralmente, nesse layout vertical, navegar do primeiro botão para cima não resultaria em nada, nem navegar do segundo botão para baixo. Agora que o botão superior definiu o botão inferior como nextFocusUp (e vice-versa), o foco da navegação mudará de cima para baixo e de baixo para cima.

Caso queira declarar uma View como focalizável na IU (quando normalmente não é), adicione o atributo XML android:focusable à View na declaração do layout. Defina o valor como verdadeiro. Também é possível declarar uma exibição como alvo de foco no Modo de Toque com android:focusableInTouchMode.

Para solicitar foco a uma determinada exibição, chame requestFocus().

Para ouvir eventos de foco (receber notificações quando uma exibição receber ou perder foco), use onFocusChange(), como discutido na seção Escutas de evento acima.