Fale sobre distribuição de eventos novamente

Fale sobre distribuição de eventos novamente

Prefácio

"Big brother, big brother, vamos lá, o líder pede que você venha para a entrevista !!"

"Estou chegando!"

Olhando para o currículo, a entrevista era para desenvolvimento intermediário do Android.

"Fale-me sobre o mecanismo de distribuição de eventos do Android!"

"Irmão mais velho, para ser honesto, não sei como distribuir o incidente. Felizmente, você levantou a mão quando me entrevistou. Você não me perguntou. Se você me perguntar, não poderei entrar em nossa empresa!"

"Levante a mão, quando estava entrevistando um estagiário, perguntei o que você está fazendo?"

"Ah, tudo bem ... Falando nisso, irmão, você pode me falar sobre a distribuição do evento?"

"Ok, vou te dizer do começo ao fim, isso será útil no futuro."

"Obrigado, irmão mais velho, vou fazer café para o irmão mais velho !!!"

texto

A distribuição de eventos é uma questão comum no desenvolvimento do Android. Não é usada apenas para lidar com entrevistas, mas também frequentemente usada no trabalho real. (Aqui eu quero explicar, geralmente tento aprender com mais firmeza, não espere até a entrevista. ) A seguir irei distribuir o evento e dar uma boa olhada!

Composição de atividades

"Rapaz, me fale sobre a composição da Activity!"

"Formulário? Atividade não é Atividade! Que composição?"

"... Lembrei-me..."

Uma Activity contém um objeto Window e Window é implementado por PhoneWindow. PhoneWindow considera DecorView como a visualização raiz de toda a janela do aplicativo, e este DecorView divide a tela em duas áreas: uma é TitleView, a outra é ContentView, e o que normalmente escrevemos é exibido em ContentView.

"Parece entender um pouco, mas irmão, o que isso tem a ver com a distribuição do evento?"

"O temperamento ansioso do macaco simplesmente não pode ser mudado, vou falar sobre isso em breve!"

Tipo de evento

Os eventos de toque correspondem à classe MotionEvent. Existem três tipos principais de eventos:

  • ACTION_DOWN é acionado quando a tela é pressionada
  • ACTION_MOVE é acionado ao deslizar na tela (a distância do movimento excede um certo limite será julgada como uma operação ACTION_MOVE)
  • ACTION_UP é acionado quando a tela é levantada
  • ACTION_CANCLE Disparado ao deslizar além do limite de controle

"Irmão, qual é o limite que você acabou de dizer? Lembro-me de ler blogs de outras pessoas e dizer o mesmo antes, mas não descobri qual é o limite?"

"Nada mal, garoto, estou muito curioso!"

TouchSlop (constante do sistema) representa o limite mínimo de movimento e o valor padrão é geralmente 8 dp. Acredito que isso pode ser entendido, o que significa que se você deslizar menos que esse valor, o sistema vai pensar que você não é um evento deslizante. Deve-se observar aqui que alguns fabricantes de telefones celulares redefinem esse valor para "melhorar a experiência do usuário". Se você não tiver certeza, pode imprimi-lo.

Log.i("ViewConfiguration", "TouchSlop=" + ViewConfiguration.get(this).scaledTouchSlop)

O seguinte é o resultado da execução:

2020-05-07 22:12:35.939 12599-12599/com.zj.weather I/ViewConfiguration: TouchSlop=21

"voce entende?"

"Uh, uh ... irmão mais velho, vá em frente, eu posso entender!"

Na verdade, a essência da distribuição de eventos do View é muito simples.Quando ocorre um evento MotionEvent, o sistema transmite o evento click para um View específico, que é o processo de distribuição dos eventos MotionEvent.

Processo de distribuição de eventos

"Rapaz, venha me dizer quais métodos são usados ​​para completar o processo de distribuição de eventos!"

"Hmm ... Existem três métodos dispatchTouchEvent, onInterceptTouchEvent e onTouchEvent concluídos."

"Nada mal, então você pode me falar sobre o processo de execução desses três métodos"

"Irmão, apenas fale diretamente, só sei que existem três métodos ..."

"Ok, não te envergonhe, eu tenho que ouvir com atenção."

Vamos falar sobre cada método um por um!

** dispatchTouchEvent (distribuição): ** Quando o método retorna verdadeiro, significa que o evento é consumido pela visualização atual; se retorna falso, significa que é entregue ao onTouchEvent na classe pai para processamento; se retornar para super.dispatchTouchEvent, significa que irá Continue a distribuir o evento.

** onInterceptTouchEvent (intercept): ** Quando o método retorna verdadeiro, significa que o evento é interceptado e entregue ao seu próprio método onTouchEvent para consumo; se retornar falso, significa que não foi interceptado e precisa ser passado para a subvisualização. Se retornar super.onTouchEvent (ev), este bloco é um pouco problemático e é dividido em dois casos:

  • Se a Visualização tiver uma Visualização filha e a Visualização filha for clicada, ela não será interceptada e continuará a ser distribuída para a Visualização filha para processamento, o que é equivalente a retornar falso
  • Se a View não tem View filho ou View filho, mas não clica na View de nêutrons (ViewGroup é equivalente a uma View normal), a resposta onTouchEvent da View será enviada para a View, o que é equivalente a retornar true.

Deve-se observar que: LinearLayout, RelativeLayout, FrameLayout e outros ViewGroups não são interceptados por padrão , enquanto ViewGroups como ScrollView e ListView podem ser interceptados , dependendo da situação específica.

** onTouchEvent (consumo): ** O valor de retorno do método é verdadeiro, o que significa que a visualização atual pode manipular o evento correspondente; o valor de retorno é falso, o que significa que a visualização atual não manipula este evento e será passado para o método onTouchEvent da visualização pai para processamento. Se ele retornar super.onTouchEvent (ev), o processamento do evento é dividido em duas situações:

  • Se a View for clicável ou longclickable, ela retornará verdadeiro, indicando que o evento foi consumido, o mesmo que retornar verdadeiro
  • Se a View não for clicável ou longclickable, ela retornará false, o que significa que o evento não será consumido e será passado para cima, assim como retornar false.

"Garoto, entendeu? A chamada distribuição de eventos é simples assim"

"Ah? O que é tudo isso! Não entendo nada, irmão, pode falar mais sobre isso?"

"Eu realmente não posso te ajudar, ok, ouça!"

Veja, existem três tipos de eventos no Android: Activity, ViewGroup e View . Você pensa, o que Activity e View fazem para interceptar eventos? Eles não se importam, então é o suficiente para distribuir e consumir. Mas o ViewGroup é diferente. Ele conterá subvisualizações, então ele precisa interceptar eventos, certo? Esqueça, escreva um pseudocódigo para você!

fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    
    
        var result = false
        if (onInterceptTouchEvent(ev)) {
    
    
            result = onTouchEvent(ev)
        } else {
    
    
            result = child.dispatchTouchEvent(ev)
        }
        return result
    }

"Rapaz, você acha que isso vai funcionar?"

"Hum ... Irmão, você pode falar sobre isso ..."

Observe o código acima, correspondente a um ViewGroup raiz, depois que um evento click for gerado, ele será passado para ele primeiro e seu método dispatchTouchEvent será chamado neste momento . Se o método onInterceptTouchEvent desse ViewGroup retornar verdadeiro, significa que ele deseja interceptar o evento atual. , Em seguida, o evento será entregue a este ViewGroup para processamento, se seu mOnTouchListener estiver definido, onTouch será chamado, caso contrário, onTouchEvent será chamado. Em onTouchEvent, se o conjunto mOnCLickListener , o onClick é invocado. Deve ser observado aqui que, enquanto um de CLICKABLE e LONG_CLICKABLE da View for true, onTouchEvent retornará true para consumir este evento; se o método onInterceptTouchEvent retornar false, significa que ele não intercepta o evento atual, e o evento atual continuará a ser passado para seus elementos filho. , Em seguida, o método dispatchTouchEvent do elemento filho será chamado e se repetirá até que o evento seja finalmente processado.

"Rapaz, não é fácil?"

"É muito simples de ouvir, mas ainda tenho que digerir!"

"Bem, de fato, esta peça é realmente muito problemática. Para colocá-lo de forma simples, será mais problemático lidar com conflitos deslizantes se vários layouts deslizantes forem aninhados. Deixe-me resumir para você!"

Pequeno resumo

  • Prioridade de entrega do evento: onTouchListener.onTouch> onTouchEvent> onClickListener.onClick
  • ViewGroup não intercepta nenhum evento por padrão (retorna falso)
  • O onTouchEvent da visualização consumirá eventos por padrão (retorna true), a menos que não seja clicável (clickable e longClickable são ambos falsos)
  • O atributo longClickable de View é falso por padrão , e o atributo clicável depende da situação.Por exemplo, o atributo clicável de Button é verdadeiro por padrão, e o atributo clicável de TextView é falso por padrão.
  • O atributo enable de View não afeta o valor de retorno padrão de onTouchEvent
  • O método requestDisallowInterceptTouchEvent pode intervir no processo de distribuição de eventos do elemento pai no elemento filho, exceto para o evento ACTION_DOWN

"Mantenha esses pontos em mente, você entenderá isso mais rápido!"

"Obrigado irmão!"

Problemas de desenvolvimento

"A propósito, quando ACTION_CANCEL será acionado? Se você tocar no botão e deslizar para fora para levantá-lo, ele acionará um evento de clique e deslizará de volta para levantá-lo?"

"Você pode fazer uma pergunta por pergunta ..."

  • Geralmente, ACTION_CANCEL e ACTION_UP são considerados como o fim do processamento do evento View. Se ACTION_UP ou ACTION_MOVE for interceptado na visão pai, no momento em que a visão pai interceptar a mensagem pela primeira vez, a visão pai especifica que a visão filho não aceita mensagens subsequentes e a visão filha receberá o evento ACTION_CANCEL.
  • Se você tocar em um controle, mas ele não for levantado (movido para outro lugar) na área do controle, ACTION_CANCEL aparecerá.

"Entendido?"

"Hmm, eu sei disso, mas ainda tenho um problema. Se o evento de clique for interceptado, mas eu quiser enviá-lo para a Visualização abaixo, o que devo fazer?"

"Isso é simples! Contanto que você substitua o método requestDisallowInterceptTouchEvent () da subclasse para retornar true, o onInterceptTouchEvent () da classe pai não será executado e o evento de clique pode ser passado para a Visualização abaixo."

"Irmão, como faço para resolver os conflitos deslizantes que costumo encontrar?"

"Isso é mais problemático de se falar, talvez eu lhe dê algumas idéias, isso precisa que você experimente lentamente em um desenvolvimento futuro!"

Regras para lidar com conflitos deslizantes:

  • Para conflitos de deslizamento causados ​​por deslizamento externo e direções de deslizamento internas inconsistentes, é possível determinar quem intercepta o evento com base na direção de deslizamento.
  • Para conflitos de deslizamento causados ​​pela consistência da direção deslizante externa e da direção deslizante interna, você pode especificar quando a Visualização externa interceptará o evento e quando a Visualização interna interceptará o evento de acordo com os requisitos do negócio.
  • Para o aninhamento das duas situações acima, é relativamente complicado, e você também pode encontrar um avanço no negócio de acordo com as necessidades.

Método de implementação de conflito deslizante:

  • Método de interceptação externa: significa que os eventos de clique são interceptados primeiro pelo contêiner pai. Se o contêiner pai precisar deste evento, ele o interceptará, caso contrário, não será interceptado. Método específico: precisa reescrever o método onInterceptTouchEvent do contêiner pai e fazer a interceptação correspondente internamente.
  • Método de interceptação interna: significa que o contêiner pai não intercepta nenhum evento, mas passa todos os eventos para o contêiner filho. Se o contêiner filho precisar desse evento, ele será consumido diretamente, caso contrário, será entregue ao contêiner pai para processamento. Método específico: precisa cooperar com o método requestDisallowInterceptTouchEvent

Resumindo

"Rapaz, isso está sempre bem?"

"Irmão mais velho, ainda tenho dúvidas ..."

"Me solta, é tão tarde, vamos conversar sobre isso amanhã se você tiver alguma dúvida!"

Este artigo descreve resumidamente o mecanismo de distribuição de eventos do Android. A descrição não é particularmente detalhada. Você pode escrever uma pequena demonstração para tentar aprofundar seu entendimento. O artigo foi escrito com pressa, se houver erros, indique-os na área de comentários, obrigado! Se você gostou, por favor, curta e siga!

Acho que você gosta

Origin blog.csdn.net/haojiagou/article/details/105987412
Recomendado
Clasificación