vista studio sirve que propiedades para libreria example clase addview java android view

java - studio - textview android



Vista personalizada... reemplaza onTouchEvent pero no performClick (4)

Recibo esta advertencia (del título de la pregunta) en una vista personalizada de Android que estoy desarrollando.

¿Por qué me avisan? ¿Cuál es la lógica detrás de esto es por qué es una buena
¿Practica también para anular performClick cuando anula onTouchEvent ?


¿Cuál es el propósito?

En algunas de las otras respuestas, puede ver formas de hacer que desaparezca la advertencia, pero es importante entender por qué el sistema quiere que anule el performClick() en primer lugar.

Hay millones de personas ciegas en el mundo. Tal vez normalmente no piensas mucho en ellos, pero deberías. Ellos usan Android, también. "¿Cómo?" usted podría preguntar Una forma importante es a través de la aplicación TalkBack . Es un lector de pantalla que da feedback de audio. Puede activarlo en su teléfono yendo a Configuración> Accesibilidad> TalkBack . Ir a través del tutorial allí. Es realmente interesante. Ahora trata de usar tu aplicación con los ojos cerrados. Probablemente encontrará que su aplicación es extremadamente molesta en el mejor de los casos y completamente rota en el peor. Eso es un error para usted y una desinstalación rápida por parte de cualquier persona con discapacidad visual.

Mire este excelente video de Google para una introducción sobre cómo hacer que su aplicación sea accesible.

Cómo anular performClick()

Veamos una vista personalizada de ejemplo para ver cómo funciona la anulación de performClick() . Haremos una aplicación de lanzamiento de misiles simple. La vista personalizada será el botón para dispararla.

Suena mucho mejor con TalkBack habilitado, pero los gifs animados no permiten el audio, así que solo tendrás que probarlo.

Código

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <net.example.customviewaccessibility.CustomView android:layout_width="200dp" android:layout_height="200dp" android:contentDescription="Activate missile launch" android:layout_centerInParent="true" /> </RelativeLayout>

Tenga en cuenta que configuro el contentDescription . Esto le permite a TalkBack leer qué es la vista personalizada cuando el usuario siente por ella.

CustomView.java

public class CustomView extends View { private final static int NORMAL_COLOR = Color.BLUE; private final static int PRESSED_COLOR = Color.RED; public CustomView(Context context) { super(context); init(); } public CustomView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setBackgroundColor(NORMAL_COLOR); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: setBackgroundColor(PRESSED_COLOR); return true; case MotionEvent.ACTION_UP: setBackgroundColor(NORMAL_COLOR); // For this particular app we want the main work to happen // on ACTION_UP rather than ACTION_DOWN. So this is where // we will call performClick(). performClick(); return true; } return false; } // Because we call this from onTouchEvent, this code will be executed for both // normal touch events and for when the system calls this using Accessibility @Override public boolean performClick() { super.performClick(); launchMissile(); return true; } private void launchMissile() { Toast.makeText(getContext(), "Missile launched", Toast.LENGTH_SHORT).show(); } }

Notas

  • La documentation también utiliza una variable mDownTouch que parece ser utilizada para filtrar eventos adicionales de retoque, pero como no está bien explicada o no es estrictamente necesaria para nuestra aplicación, la mDownTouch . Si creas una verdadera aplicación de lanzamiento de misiles, te sugiero que busques más en esto.
  • El método principal que lanza el misil ( launchMissile() ) solo se llama desde performClick() . Tenga cuidado de no llamar dos veces si también lo tiene en onTouchEvent . Deberá decidir exactamente cómo y cuándo llamar a su método de lógica de negocios en función de los aspectos específicos de su vista personalizada.
  • No performClick() y luego no haga nada con él solo para deshacerse de la advertencia. Si quiere ignorar a los millones de personas ciegas en el mundo, entonces puede suprimir la advertencia. Al menos así eres honesto acerca de tu falta de corazón.

    @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { ... }

Estudio adicional


Algunos servicios de accesibilidad no llaman al onTouchEvent , como se explica al hacer clic en el enlace "más ..." en los detalles de advertencia.

Se recomienda que anule performClick para la acción deseada, o al menos anule junto a su onTouchEvent .

Si su código es más adecuado para el evento táctil, puede usar algo similar a:

@Override public boolean performClick() { if (actionNotAlreadyExecuted) { MotionEvent myEvent = MotionEvent.obtain(long downTime, long eventTime, int action, float x, float y, int metaState); onTouch(myView, myEvent); } return true; // register it has been handled }

Más información sobre el acceso a eventos táctiles a través del código está disponible en el evento de activación de tal evento programáticamente


Aunque es solo una advertencia y podría ser ignorado, parece ser necesario para la accesibilidad.

Los detalles se describen here

Luego, cuando gestione una acción, debe agregar el performClick, es decir:

if (action == MotionEvent.ACTION_DOWN) { performClick(); // Call this method to handle the response, and // thereby enable accessibility services to // perform this action for a user who cannot // click the touchscreen.


Esta advertencia le dice que anule performClick

@Override public boolean performClick() { // Calls the super implementation, which generates an AccessibilityEvent // and calls the onClick() listener on the view, if any super.performClick(); // Handle the action for the custom click here return true; }

Pero no es obligatorio. Como he creado un knobView personalizado y está funcionando bastante bien, también estoy viendo esta advertencia.