Advertencia de onTouchListener: onTouch debe llamar a View # performClick cuando se detecta un clic


108

He creado un onTouchListener. Desafortunadamente, el método onTouch () throwsme advierte:

com/calculator/activitys/Calculator$1#onTouch should call View#performClick when a click is detected

¿Qué significa? No he encontrado ninguna información sobre esta advertencia. Aquí está el código completo:

LinearLayout llCalculatorContent = (LinearLayout) fragmentView.findViewById(R.id.calculator_content);

llCalculatorContent.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Tools.hideKeyboard(getActivity(), getView());
        getView().clearFocus();
        return false;
    }   
});

17
desea deshacerse de la advertencia solo llame v.performClick(). La implementación reproducirá un pequeño sonido (si lo tiene habilitado en su dispositivo) y llamará al onClickListener, que probablemente no haya anulado
Blackbelt

Tu respuesta fue correcta. Gracias
Trzy Gracje

Respuestas:


128

Aqui tienes:

public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        //some code....
        break;
    case MotionEvent.ACTION_UP:
        v.performClick();
        break;
    default:
        break;
    }
    return true;
}

14
¿No debería llamarse solo cuando el evento == MotionEvent.Action_UP, o algo así? Además, ¿devolver "falso" no llamaría realmente al método de clic original, por lo que debería devolver "verdadero" en su lugar?
desarrollador de Android

@longilong Bueno, si lo desea, también puede configurarlo para usar switch-case, pero lógicamente es lo mismo ...
desarrollador de Android

3
Tengo una advertencia similar. Pero mi escenario es un poco diferente ya que estoy configurando un OnTouchListener anónimo cuando configuro RecyclerView (llamando a myRecyclerView.setOnTouchListener. Android Studio está marcando toda la clase anónima con una advertencia similar e incluso si agrego v.performClick, la advertencia permanece.
fr4gus

8
si devolvemos false de este método, no deberíamos estar obligados a llamar performClick, ¿verdad? En este caso, no entiendo por qué la advertencia de pelusa sigue ahí
Jiechao Wang

9
No hace nada para corregir la advertencia.
TheLibrarian

2

Puede suprimir la pelusa

@SuppressLint("ClickableViewAccessibility")

Deberías llamar performClick()adentro onTouchEvent().

@Override
public boolean onTouchEvent(MotionEvent event) {
    //A logic 

    performClick();
    return super.onTouchEvent(event);
}

o

findViewById(R.id.view1).setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        v.performClick();

        return v.onTouchEvent(event);
    }
});

OnTouch fluir

Leer más aquí


1
No tiene que anular performClick(). Comparta su código
yoAlex5

1

En caso de que no esté utilizando un Custom Viewque anula explícitamente onPerformClick, la advertencia no se eliminará simplemente siguiendo la respuesta de Secko.

Además de su respuesta, para hacer lo mismo en clases como android.widget.Buttono Buttonnecesita hacer una vista personalizada simple que amplíe la vista de destino.

Ejemplo:

La clase de vista personalizada:

public class UselessButton extends AppCompatButton {
    public UselessButton(Context context) {
        super(context);
    }

    public UselessButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public UselessButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }
}

XML :

<stackoverflow.onEarth.UselessButton
    android:id="@+id/left"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:layout_marginEnd="8dp"
    android:layout_marginBottom="8dp"
    android:background="@drawable/left"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.16"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBaseline_toBaselineOf="@+id/right"
    app:layout_constraintVertical_bias="0.5" />

Java :

    left.setOnTouchListener((v, event) -> {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            enLeft = 1;
            enRight = 0;
            return true;
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            enLeft = 0;
            v.performClick();
            return false;
        } else {
            return false;
        }
    });

Problemas actuales: IDE resuelve la advertencia, pero no puede ver esta acción de hacer clic prácticamente en un dispositivo Android real.

EDITAR : Se corrigió la obtención del evento de clic: UsarView.setPressed(boolean)

down.setOnTouchListener((v, event) -> {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        enFront = 0;
        enBack = 1;
        left.setPressed(true);
        return true;
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        enBack = 0;
        v.performClick();
        v.setPressed(false);
        return false;
    } else {
        return false;
    }

0

simplemente llame al método performClick, así:

@Override
public boolean onTouch(View v, MotionEvent event) {
    v.performClick();
    Tools.hideKeyboard(getActivity(), getView());
    getView().clearFocus();
    return false;
}   

0

Tuve un problema similar con a MultiTouchListenery lo resolví implementando GestureDetectoray escuchando a SingleTap(Esto no elimina la advertencia pero comienza a activar onClickeventos en mi vista)

class TouchListener(context: Context) : MultiTouchListener() {

    private var tochedView: View? = null
    private var mGestureDetector = CustomGestureDetector()
    private var gestureDetector: GestureDetector = GestureDetector(context, mGestureDetector)

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouch(view: View?, event: MotionEvent?): Boolean {
        val aux = super.onTouch(view, event)

        tochedView = view
        gestureDetector.onTouchEvent(event)

        return aux
    }

    private inner class CustomGestureDetector: GestureDetector.SimpleOnGestureListener() {

        override fun onSingleTapUp(e: MotionEvent?): Boolean {
            // this will be called even when a double tap is
            tochedView?.performClick()
            return super.onSingleTapUp(e)
        }

        override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
            // this will only be called after the detector is confident that the
            // user's first tap is not followed by a second tap leading to a double-tap gesture.
            tochedView?.performClick()
            return super.onSingleTapConfirmed(e)
        }

    }

}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.