page.title=Eventos de entrada parent.title=Interface do usuário parent.link=index.html @jd:body
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 isto.
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 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 isto, 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 a sua passagem para capturar a interação do usuário com a IU.
Geralmente, as escutas de evento são usadas para escutar 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 {@link android.widget.Button} para deixar algo mais extravagante. Neste caso, você poderá definir os comportamentos de evento padrão para a classe usando manipuladores de evento.
Uma escuta de evento é uma interface na classe {@link android.view.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()
onLongClick()
onFocusChange()
onKey()
onTouch()
onCreateContextMenu()
Esses métodos são os únicos habitantes de suas 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()
. (Ex.:, chame
{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}
e passe-o à implementação de {@link android.view.View.OnClickListener 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. Isto 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, apresenta-se a razão:
{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}
-
Isto retorna um booleano para indicar se você consumiu o evento e se ele deve ser levado adiante.
Ou seja, ele retorna verdadeiro para indicar que você lidou com o evento e não deve seguir adiante;
ou retorna falso caso você não tenha lidado com ele e/ou o evento deva continuar para qualquer
outra escuta de clique.{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}
-
Isto retorna um booleano para indicar se você consumiu o evento e se ele deve ser levado adiante.
Ou seja, ele retorna verdadeiro para indicar que você lidou com o evento e não deve seguir adiante;
ou retorna falso caso você não tenha lidado com ele e/ou o evento deva continuar para qualquer
outra escuta de tecla.{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}
-
Isto retorna um booleano para indicar se a escuta consome este evento. O importante é que este evento
pode possuir várias ações que se seguem mutuamente. 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 à vista atualmente em foco. Eles são enviados a partir da parte superior
da hierarquia de vistas e segue à parte inferior até atingir o destino adequado. Se a vista (ou um filho da vista)
estiver em foco, é possível ver o percurso do evento pelo método {@link android.view.View#dispatchKeyEvent(KeyEvent)
dispatchKeyEvent()}
. Como uma alternativa para capturar eventos de tecla por meio da vista, também é possível
receber todos os eventos dentro da Atividade com {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}
e {@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}
.
Além disso, ao pensar sobre a entrada de texto para o aplicativo, lembre-se de que vários dispositivos possuem 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 {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}
. Nunca deve-se 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 nestes métodos para validar a entrada quando o usuário pressiona a tecla
de retorno; em vez disso, use ações como {@link android.view.inputmethod.EditorInfo#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 a partir 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 vista. Portanto, certifique-se de que quer encerrar o evento ao retornar verdadeiro.
Se estiver compilando um componente personalizado a partir de View, então 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:
{@link android.view.View#onKeyDown}
- Chamado quando um novo evento de tecla ocorre.{@link android.view.View#onKeyUp}
- Chamado quando um evento de tecla para cima ocorre.{@link android.view.View#onTrackballEvent}
- Chamado quando um evento de movimento do cursor de bola ocorre.{@link android.view.View#onTouchEvent}
- Chamado quando um evento de movimento de toque ocorre.{@link android.view.View#onFocusChanged}
- Chamado quando a vista ganha ou perde foco.Há alguns outros métodos que você deve ter ciência que não fazem parte da classe View, mas podem ter impacto direto na maneira de lidar com os eventos. Portanto, ao gerenciar eventos mais complexos dentro de um layout, considere esses outros métodos:
{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
Activity.dispatchTouchEvent(MotionEvent)}
- Isto permite que {@link
android.app.Activity} intercepte todos os evento de toque antes de serem enviados à janela.{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
ViewGroup.onInterceptTouchEvent(MotionEvent)}
- Isto permite que {@link
android.view.ViewGroup} assista aos eventos à medida que são enviados para as vistas filho.{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
ViewParent.requestDisallowInterceptTouchEvent(boolean)}
- Chame isto
sobre uma Vista pai para indicar que ela não deve interceptar eventos de toque com {@link
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}
.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, então não é mais necessário destacar itens ou fornecer foco para uma vista 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 deste ponto, somente vistas que tiverem {@link android.view.View#isFocusableInTouchMode} como verdadeiro poderão ter foco, como widgets de edição de texto. Outras vistas 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 vista 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 (todas as janelas e atividades). Para consultar o estado atual, é possível chamar {@link android.view.View#isInTouchMode} para ver se o dispositivo está no modo de toque no momento.
A estrutura lidará com a rotina de movimento de foco em resposta à entrada do usuário.
Isto inclui a mudança de foco à medida que as vistas são removidas ou ocultadas, ou à medida que novas
vistas se tornem disponíveis. As vistas indicam a prontidão para receber foco
por meio do método {@link android.view.View#isFocusable()}
. Para determinar se uma vista pode receber
foco, chame {@link android.view.View#setFocusable(boolean) setFocusable()}
. Quando no modo de toque,
é possível consultar se uma vista permite foco com {@link android.view.View#isFocusableInTouchMode()}
.
É possível alterar isto com {@link android.view.View#setFocusableInTouchMode(boolean) 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 substituições explícitas com os seguintes atributos XML no arquivo do layout: nextFocusDown, nextFocusLeft, nextFocusRighte nextFocusUp. Adicione um desses atributos à vista a partir do foco que ela está abandonando. Defina o valor do atributo para ser o ID da vista 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, neste layout vertical, navegar para cima a partir do primeiro botão não resultaria em nada, nem navegar para baixo a partir do segundo botão. Agora que o botão superior definiu o botão do fundo como nextFocusUp (e vice-versa), o foco da navegação alternará de "cima para baixo" e "baixo para cima".
Caso queira declarar uma vista como alvo de foco na IU (quando tradicionalmente não é),
adicione o atributo XML android:focusable
à vista, na declaração do layout.
Defina o valor como verdadeiro. Também é possível declarar uma vista
como alvo de foco no Modo de Toque com android:focusableInTouchMode
.
Para solicitar foco a uma determinada Vista, chame {@link android.view.View#requestFocus()}
.
Para ouvir eventos de foco (receber notificações quando uma vista receber ou perder foco), use
{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}
,
como discutido na seção Escutas de evento acima.