A seguir, é apresentado um exemplo de evento depois de clicar em uma visualização.
Primeiro, analise o método DispatchTouchEvent () na visualização, que é o primeiro método a ser executado clicando na visualização.
public boolean DispatchTouchevent (Evento MotionEvent) {if (MOTTOTHOUSTER! = NULL && (MVIEWFLAGS & HABORD_MASK) == Enabled && MontouchListener.ontouch (this, evento)) {return true; } retornar otechevent (evento);}NOTA: Ele contém duas funções de retorno de chamada oTouch () e OnTouchEvent (); Se o controle estiver ligado ao OnTouchListener e o controle for ativado, execute o método oTouch (). Se o método retornar TRUE, significa que o evento de toque foi consumido pelo ouvinte OTOTOUSHListener e não será distribuído para baixo; Mas se retornar falso, significa que ele não foi consumido e continua sendo distribuído para baixo para o OnTouchEvent () do controle para o processamento.
Em seguida, analise o método OnTouchEvent () e execute mais o processamento de eventos de toque.
if (((viewflags & clickable) == clickable || (viewflags & long_clickable) == long_clickable)) {switch (event.getAction ()) {case MotionEvent.action_up: ..... // responda para clicar em quebra de evento; case MotionEvent.action_down: .... quebre; case MotionEvent.action_cancel: .... quebre; case MotionEvent.action_move: ..... quebre; } retornar true; } retornar false;Se o controle for clicável ou long_clickable, ele poderá responder ao evento correspondente e retornar true após a conclusão da resposta para continuar a resposta. Por exemplo, ao clicar em um evento, primeiro responda ao Action_down, depois quebre e retorne TRUE, depois levante a mão, depois a distribua do DispatchTouchEvent () e depois responderá ao Action_Up e o performaClick () responderá ao Click Event.
Responda aos eventos de clique
public boolean performClick () {sendAccessibilityEvent (acessibilidadeEvent.Type_View_Clicked); if (monclicklistener! = null) {playoundeffect (sonorefftConstants.click); MoClickListener.OnClick (isto); retornar true; } retornar false;}Execute MoClickListener.OnClick (isto); Ou seja, a função onclick () que liga o ouvinte.
Pontos -chave:
Como usar a diferença entre OnTouch e OnTouchEvent?
responder:
Quando o controle de visualização recebe um evento de toque, se o controle estiver vinculado a um ouvinte oTouchListener e o controle for ativado, execute o método oTouch (). Se for verdade, o evento de toque foi consumido e não será mais transmitido; Se False for devolvido, continue ligando para o evento OnTouchEvent ().
Depois que o evento Android Touch for passado para a Decorview (um Framelayout) no topo da atividade, ele será passado por camada por camada através do ViewGroup para a árvore de exibição e, finalmente, passará o evento para a visão real recebida. Aqui estão alguns métodos importantes.
DispatchTouchEvent
Quando um evento é passado para um grupo de vista, o DispatchTouchEvent será chamado. O código foi excluído
public boolean DispatchTouchevent (MotionEvent EV) {boolean manipulado = false; if (onFilterToucheventForSecurity (EV)) {final int Action = ev.getAction (); final int ActionMasked = Action & MotionEvent.Action_Mask; // Atenção 1: Limpe alguns estados quando pressionado se (ActionMasked == MotionEvent.action_down) {cancellandcleartouchTargets (EV); // Observe este método resettouchState (); } // Atenção 2: Verifique se o booleano final interceptado precisa ser interceptado; // Se você acabou de pressionar ou tiver uma visualização infantil para lidar com isso se (actionMasked == MotionEvent.action_down || mfirstTouchTarget! = Null) {final boolean desalouvecept = (mGroupFlags & flag_disallow_intercept)! = 0; if (! desaloundIntercept) {interceptado = onInterceptTouchEvent (EV); Ev.SetAction (Ação); // Restaurar a ação no caso de ter sido alterada} else {intercepted = false; }} else {// não é o começo de uma sequência de ação e não há subview para lidar com isso. Interceptado diretamente = true; } // O evento não é cancelado e não é interceptado pelo grupo ViewGroup atual. Vá ver se há uma subview tomada se (! Cancelada &&! Interceptada) {// Se este é o começo de uma série de ações ou houver um novo ponteiro pressionado, precisamos encontrar a subview que pode lidar com este ponteiro se (ação motionMasked == MotionEvent.Action_Down | MotionEvent.action_hover_move) {final int actionIndex = ev.getActionIndex (); // Sempre 0 para baixo // A limitação acima do ponto de toque 32 é que ele causa o final Int IdbitSTOASSIGN = dividido? 1 << ev.getPointerID (ActionIndex): TouchTarget.all_Pointer_ids; Final Int Childrencount = MCHILDRENCOUNT; if (newTouchTarget == null && Childrencount! = 0) {Final Float X = ev.getx (ActionIndex); flutuação final y = ev.gety (ActionIndex); // Classifique todas as visualizações do ChildGroup e coloque -as na camada superior para iniciar. Final ArrayList <View> pré -orderedList = BuildOrderEdChildList (); Final Boolean CustomOrder = pré -orderedList == NULL && isCHILDRENDRAWINGORDERENBLEABLE (); Visualização final [] crianças = mchildren; para (int i = Childrencount-1; i> = 0; i--) {final int ChildIndex = CustomOrder? GetChildDrawingOrder (ChildCount, i): i; Final View Child = (pré -encomendedList == NULL)? crianças [ChildIndex]: pré -encomendedlist.get (ChildIndex); // CanViewReCeivePointerEvents Vista visível pode aceitar eventos // istransformedTouchPoTHPoTIVIVEVEVELECIMENTO DEVIDO se enquadra na área de cliques se (! CanViewReceivePointerEvents (Child) ||!! continuar; } // pode lidar se a visão deste ponteiro processou o ponteiro anterior e use newTouchTarget = getTouchTarget (filho); if (newTouchTarget! = null) {// Child já está recebendo toque dentro de seus limites. // Dê o novo ponteiro, além dos que está lidando. newTouchTarget.PointerIdBits | = IdbitStoassign; quebrar; }} // Atenção 3: Envie -o diretamente para a visualização da criança se (DispatchTransformedTouchEvent (EV, False, Child, Idaassign)) {// Child deseja receber toque dentro de seus limites. mLASTTOUCHdownTime = ev.getDownTime (); if (pré -encomendedlist! = null) {// ChildIndex aponta para a lista presortada, encontre o índice original para (int j = 0; j <Childrencount; j ++) {if (crianças [ChildIndex] == mChildren [j]) {mlastTouchDownIndex = j; quebrar; }}} else {mlastTouchDownIndex = ChildIndex; } mlastTouchdownx = ev.getx (); mLASTTOUCHDOWNY = EV.GETY (); newTouchTarget = addTouchTarget (criança, idbitstoassign); jádispatchedTonewTouchTarget = true; quebrar; }}}}}} // A visualização da criança que recebeu o evento já foi encontrada antes. Se for nulo, significa que não há vista para a criança para assumir o controle. O ViewGroup atual precisa lidar se (mfirstTouchTarget == NULL) {// ViewGroup manipulado = DispatchTransformedTouchEvent (EV, Cancelchild, Null, TouchTarget.all_Pointer_ids); } else {if (jádispatchedTonewTouchTarget) {// ignora algum código se (despachoTransformedToCharevent (eV, cancelchild, Target.child, Target.PointerIDBits)) {manipulado = true; }}} Retorno manipulado;}A atenção no código acima estará envolvida na parte posterior, então preste atenção a ele.
Deve -se apontar aqui que diferentes dicas em uma série de ações podem ser atribuídas a diferentes visualizações para responder. O ViewGroup manterá um ponteiro e uma lista de TouchTetgets que lidam com as visualizações. Um TouchTarget representa uma subview que pode lidar com ponteiros. Obviamente, uma visualização pode lidar com vários ponteiros, como os dois dedos estão em uma área de Subview. O TouchTarget usa um Int Internamente para armazenar o ponteiro que ele pode processar e um bits INT32, e é por isso que a camada superior só pode permitir até 32 pontos de toque ao mesmo tempo.
Vejamos o código da atenção 3. Frequentemente dizemos que, se o despachoCouchEvent da visualização retornar FALSE, ela não poderá ser seguida pela ação. Por que isso? Porque se o False for devolvido na Atenção 3, ele não será registrado no TouchTarget, o ViewGroup acredita que você não tem a capacidade de lidar com este evento.
Você pode ver aqui que o ViewGroup realmente lida com eventos no DispatchTransformedTouchEvent, siga e dê uma olhada:
DispatchTransformedToucheEventPrivate boolean DispatchTransformedToucheEvent (Evento de MotionEvent, cancelamento booleano, visualize Child, int desesedPointerIdBits) {// no processamento de subclasse, deixe -o para o ViewGroup para processamento se (Child == Null) {manipulado = Super.DispToCheVent (transformados (Child === Null) {manipulado = Super.DispToChevent (transformoughevent; } else {final float offsetx = mscrollx - Child.mleft; Offsety Final Float = msCrolly - Child.mtop; transformEDevent.OffSetLocation (OffsetX, Offsety); if (! Child.HasIdityMatrix ()) {transformEDevent.Transform (Child.getInversematrix ()); } manipulado = Child.dispatchTouchEvent (transformEDevent); } retornar manipulado;}Você pode ver que, não importa o quê, o DispatchTouchEvent da visualização será chamado, que é onde o evento de cliques é realmente tratado.
DispatchTouchEvent public boolean DispatchTouchEvent (Evento MotionEvent) {if (OnFilterTouchEventForSecurity (Event)) {// Obtenha o evento OTTOUCH da exibição primeiro, se o oTouch retornar o verdadeiro ouvinte Li = Mlistenerinfo; if (li! = null && li.montouchListener! = null && (mviewflags & enabled_mask) == ativado && li.montouchListener.ontouch (this, event)) {resultado = true; } if (! Result && otouchevent (event)) {resultado = true; }} Retornar resultado; }O evento OnTouch que definimos para a visualização é uma prioridade mais alta. Se a execução do oTouch retornar true, o OnTouchEvent da visualização não irá para a vista. Alguns de nossos eventos de cliques são tratados no OnTouchEvent, e é por isso que o OnTouch retorna true, e os eventos relacionados ao clique da visualização não serão processados.
Um breve resumo deste processo
Quando o ViewGroup aceita eventos transmitidos pelos superiores, se for o começo de uma série de eventos de toque (Action_down), o ViewGroup verá primeiro se ele precisa interceptar o evento (onInterceptTouchEvent, a implementação padrão do ViewGroup retorna diretamente para indicar que isso não intercepta) e depois o ViewGroup traves. Encontre a visualização que você está clicando e ligue imediatamente para o DispatchTouchEvent da visualização de destino. Se o despatchTouchEvent da visualização de destino retornar FALSE, ele pensa que a visualização de destino está apenas nessa posição. Ele não quer aceitar este evento, mas só quer fazer uma visão silenciosamente (eu assisto quieto você fingindo*). Neste momento, o ViewGroup também irá para o DispatchTouchEvent, feito!