OnTouch works, but OnClickListener doesn't?

梦想与她 提交于 2019-12-18 03:04:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!