onTouchListener warning: onTouch should call View#performClick when a click is detected
AndroidOntouchlistenerAndroid Problem Overview
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;
}
});
Android Solutions
Solution 1 - Android
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 - Android
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);
}
});
Read more here
Solution 3 - Android
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 - Android
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 - Android
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)
}
Solution 6 - Android
I had a similar issue with a MultiTouchListener
and solved it implementing a GestureDetector
and listening for a SingleTap
(This does not remove the warning but starts to triggering onClick
events on my view)
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)
}
}
}
Solution 7 - Android
this is super late answer but I hope it will help somebody. I faced this warning a while ago and my approach was, made a class extending View.class
then made a public method inside that class called it closeKeyboard(View view){}
this is how it looks:
public class MyTouchEvent extends View {
public MyTouchEvent(Context context) {
super(context);
}
public void closeKeyboard(View view) {
view.setOnTouchListener((view1, motionEvent) -> {
view1.performClick();
// this is a library handels the closing of keyboard
UIUtil.hideKeyboard((Activity) getContext());
return false;
});
}
@Override
public boolean performClick() {
super.performClick();
return true;
}
}
in the MainActivity
I called the closeKeyboard(view)
and used the parent layout as parameter like this:
new MyTouchEvent(this).collapseKeyboard(parentLayout);
the library used to close the keyboard
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'
Solution 8 - Android
I had to ignore it. I had a TouchListener to cause an animated button push (change color in my case). But I also had a click listener to do the button work. So this caused my click listener to fire again. I tried it as a default case in the switch of Touch Events (Action_Down, Up, etc..)