onTouchListener warning: onTouch should call View#performClick when a click is detected

I have created a onTouchListener. Unfortunately onTouch() method throws me a warning:

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

What does it mean? I have not found any information about this warn. Here is the full code:

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;
    }   
});

Solution 1:

Here you go:

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;
}

Solution 2:

onTouch should call View#performClick when a click is detected

You can suppress the Lint

@SuppressLint("ClickableViewAccessibility")

You should call performClick() inside onTouchEvent().

@Override
public boolean onTouchEvent(MotionEvent event) {
    //Logic 
    performClick();
    return super.onTouchEvent(event);
}

or

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

OnTouch flow

Read more here

Solution 3:

In case you're not using a Custom View which explicitly overrides onPerformClick , the warning won't get removed by just following Secko's answer.

In addition to his answer, for doing the same on classes like android.widget.Button or Button you need to make a simple custom view which extends the target view.

Example :

The Custom View Class:

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;
        }
    });

Current problems : Warning gets resolved by IDE, but can't see this practically performing click action on a real Android Device.

EDIT: Fixed getting the click event : Use View.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;
    }

Solution 4:

just call performClick method, like this:

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

Solution 5:

I solved this warning by using Kotlin Extensions

First create the extension (Eg. ViewExtensions.kt)

fun Button.onTouch(touch: (view: View, motionEvent: MotionEvent) -> Unit) {
    setOnTouchListener { v, event ->
        touch(v,event)
        v.performClick()
        true
    }
}

Second, in your Fragment or activity create a function

private fun onTouchButton(v: View, event: MotionEvent) {
       /* My Amazing implementation */
}

Finally, use the extension

myButton.onTouch { v, event ->
 onTouchButton(v, event)
}