Receiving onTouch and onClick events with Android

2019-02-10 01:44发布

I have a view that need to process onTouch gestures and onClick events. What is the proper way to achieve this?

I have an onTouchListener and an onClickListener set on the view. Whenever I do touch the view, first the onTouch event is triggered and later the onClick. However, from the onTouch event handler I have to return either true or false. Returning true means that the event is being consumed, so the android event system will not propagate the event any further.

Therefore, an onClick event is never generated, atleast my onClick listener is never triggered when I return true in my onTouch event handler. On the other hand, returning false there is not an option, since this prevents the onTouch listener from receiving any further events that are necessary in order to recognize a gesture. What's the usual way of solving this?

7条回答
虎瘦雄心在
2楼-- · 2019-02-10 02:12
@Override
    public boolean onTouch(View v, MotionEvent event) {


        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                layOutParams.x = initialX + (int) (event.getRawX() - initialTouchX);
                layOutParams.y = initialY + (int) (event.getRawY() - initialTouchY);

                break;
            case MotionEvent.ACTION_DOWN:
                initialX = layOutParams.x;
                initialY = layOutParams.y;
                initialTouchX = event.getRawX();
                initialTouchY = event.getRawY();
                if (initialTouchX == event.getRawX() && initialTouchY == event.getRawY()) {
                    return false;// to handle Click
                }
                break;
            case MotionEvent.ACTION_UP:
                if (initialTouchX == event.getRawX() && initialTouchY == event.getRawY()) {
                    return false;// to handle Click
                }
                break;

        }
        return true;

    }
};
查看更多
爷、活的狠高调
3楼-- · 2019-02-10 02:23
isMove = false;
case MotionEvent.ACTION_DOWN:
//Your stuff
isMove = false;
case MotionEvent.ACTION_UP:
if (!isMove || (Xdiff < 10 && Ydiff < 10 ) {
view.performClick; //The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little
even when you just click it   
}
case MotionEvent.ACTION_MOVE:
isMove = true;

Another way is to use threads. That is on Action_Down start a thread to increment a counter. In case of Action_UP : stop/interrupt the thread. look for counter if it is less than 2 (say or threshold as per your application) or !isMove then invoke click function

查看更多
迷人小祖宗
4楼-- · 2019-02-10 02:23

I've been able to implement OnClick and OnTouch together in a custom keyboard I'm building. You can take a look at this code and modify it according to your context since you didn't include a code sample to work from.

If you post a sample of your code I can modify this sample of mine to accomplish the same outcome for your use. Context is everything when it comes to Android Development. Take a look at this code snippet and see if it helps. Otherwise post a sample of your own and I'll make the modifications and reply back.

        View DefaultphaseLay() {

        LinearLayout mViewFirstPhase = (LinearLayout) getLayoutInflater().inflate(R.layout.layout_default_phase, parent);

        ksOne_btn_LiLay = (LinearLayout) mViewFirstPhase.findViewById(R.id.ksOne_btn_LiLay);
        ksOne_btn = (Button) mViewFirstPhase.findViewById(R.id.ksOne_btn);
        ksOne_btn.setOnClickListener(mCorkyListener);
        ksOne_btn.setFocusableInTouchMode(true);
        ksOne_btn.setFocusable(true);
        ksOne_btn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    playClick(keyCode);
                    //v.startAnimation(animScale);
                    //key_sound.start();
                    xkeys_lay.setVisibility(View.GONE);
                    numkeys_lay.setVisibility(View.GONE);
                    if (Constants.HapticFeedbackConstant) {
                        myVib.vibrate(Constants.vibration_duration);
                    }
                } else if (event.getAction() == MotionEvent.ACTION_UP) {
                    ksOne_btn.setFocusable(false); //Check This Added This In Attempt to Kill Selector on Action_Up
                    //playClick(-100);
                    //key_sound.pause();
                }
                return false;
            }
        });

        ChangeKeyBackgroundMehods.initChange_Key_Background(ksOne_btn_LiLay);
        ChangeFontStyle.initChange_fontStyle(ksOne_btn, getApplicationContext());
        ChangeFont_size.initChange_fontSize(ksOne_btn, getApplicationContext());

This works for the context of type alpha or numerical output, if the event is looking to send or consume some other context it would need to be modified.

查看更多
一纸荒年 Trace。
5楼-- · 2019-02-10 02:24

if you use onTouchListener , you don't have to use onClickListener. in onClickListener what it does is it get the touch event and check event actions and detect the click. so if you want to do some work when onClick. you can do it in the onTouchListener by filtering the action.

public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
    //this is touch

}
if (event.getAction() == MotionEvent.ACTION_UP) {
    //this is click

}
return false;
}
查看更多
何必那么认真
6楼-- · 2019-02-10 02:25

I agree with jdx, if you use onTouchlistener you dont need to use onclicklistener and viceversa, if you want to trigger an event on button,image,or textview click, then just fire onClicklistener. if you want some animations like dragging and spinning then use ontouchlistener to get the coordinates of the surface touched

查看更多
ゆ 、 Hurt°
7楼-- · 2019-02-10 02:29

In you GestureDetector, you can call callOnClick() directly. Note the View.callOnClick API requires API level 15. Just have a try.

 // Create a Gesturedetector
GestureDetector mGestureDetector = new GestureDetector(context, new MyGestureDetector());

// Add a OnTouchListener into view
m_myViewer.setOnTouchListener(new OnTouchListener()
{

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        return mGestureDetector.onTouchEvent(event);
    }
});

private class MyGestureDetector extends GestureDetector.SimpleOnGestureListener
{
    public boolean onSingleTapUp(MotionEvent e) {
        // ---Call it directly---
        callOnClick();
        return false;
    }

    public void onLongPress(MotionEvent e) {
    }

    public boolean onDoubleTap(MotionEvent e) {
        return false;
    }

    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }

    public boolean onSingleTapConfirmed(MotionEvent e) {
        return false;

    }

    public void onShowPress(MotionEvent e) {
        LogUtil.d(TAG, "onShowPress");
    }

    public boolean onDown(MotionEvent e) {            
        // Must return true to get matching events for this down event.
        return true;
    }

    public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, float distanceY) {
        return super.onScroll(e1, e2, distanceX, distanceY);
    }        

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        // do something
        return super.onFling(e1, e2, velocityX, velocityY);
    }
}
查看更多
登录 后发表回答