问题
I created a widget/control that I can reuse which I created by extending RelativeLayout
. Then, in one of my Activities, I created a bunch of these widgets in a loop. However, I ran into an issue when I wanted to have each widget respond to a click.
I found that setting OnTouchListener
works:
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
//Triggers debug message
}
});
but OnClickListener
doesn't:
this.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
//Doesn't trigger debug message
}
});
Why is this?
回答1:
Here are a few things to check to make sure your views are clickable:
View.setClickable()
View.setEnabled()
View.setFocusable()
View.setFocusableInTouchMode()
Depending on the exact behavior you hope to get, you'll need to set one or more of those to on. Since you are getting onTouch events, my guess is that you need to setClickable. But i'd have to see the view creation code to be sure.
回答2:
You should make sure that the TouchListener is not 'consuming' the touch event. If you return true from the onTouch()
method, Android will consider it consumed and not pass it on to the other various touch handlers (which I am assuming will include the ClickListener).
You should do:
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
//Triggers debug message
return false;
}
});
回答3:
Are you returning the boolean onTouch value properly?
From the docs:
onTouch() - This returns a boolean to indicate whether your listener consumes this event. The important thing is that this event can have multiple actions that follow each other. So, if you return false when the down action event is received, you indicate that you have not consumed the event and are also not interested in subsequent actions from this event. Thus, you will not be called for any other actions within the event, such as a finger gesture, or the eventual up action event.
EDIT
Found the solution in this question and just tried it out myself.
You need to use this return super.onTouchEvent(event);
in your onTouchEvent code. After adding this the OnClickListener started working.
回答4:
To perform this return false in your onTouch()
like this:
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
return false;
}
});
回答5:
You can Implement an onClickListener via onTouchListener:
webView.setOnTouchListener(new View.OnTouchListener() {
public final static int FINGER_RELEASED = 0;
public final static int FINGER_TOUCHED = 1;
public final static int FINGER_DRAGGING = 2;
public final static int FINGER_UNDEFINED = 3;
private int fingerState = FINGER_RELEASED;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
if (fingerState == FINGER_RELEASED) fingerState = FINGER_TOUCHED;
else fingerState = FINGER_UNDEFINED;
break;
case MotionEvent.ACTION_UP:
if(fingerState != FINGER_DRAGGING) {
fingerState = FINGER_RELEASED;
// Your onClick codes
}
else if (fingerState == FINGER_DRAGGING) fingerState = FINGER_RELEASED;
else fingerState = FINGER_UNDEFINED;
break;
case MotionEvent.ACTION_MOVE:
if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING) fingerState = FINGER_DRAGGING;
else fingerState = FINGER_UNDEFINED;
break;
default:
fingerState = FINGER_UNDEFINED;
}
return false;
}
});
回答6:
If you override the onMotionEvent() method for some reason and you need to return true/false in that case, you can manually trigger the OnClickListener() callback by calling this.performClick() inside the overridden onMotionEvent() just before you return true/false.
回答7:
When you need both onClick and onTouch events on the same view, use a GestureDetector.
回答8:
If you have tried returning false:
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
return false;
}
});
and it didn't work, try this solution if you are using ScrollView. Add a LinearLayout inside the ScrollView. Set clickable to true in it. Call setOnClickListener and setOnTouchListener from the LinearLayout.
<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbarStyle="outsideOverlay">
<LinearLayout
android:id="@+id/linearlayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="vertical">
<content... />
</LinearLayout>
</ScrollView>
LinearLayout linearlayout = findViewById(R.id.linearlayout);
linearlayout.setOnClickListener...
linearlayout.setOnTouchListener...
来源:https://stackoverflow.com/questions/5283293/ontouch-works-but-onclicklistener-doesnt