11

我有一个需要处理 onTouch 手势onClick 事件的视图。实现这一目标的正确方法是什么?

我在视图上有一个onTouchListener和一个onClickListener集合。每当我触摸视图时,首先onTouch触发事件,然后触发onClick. 但是,从onTouch事件处理程序我必须返回trueor false。返回true意味着事件正在被消费,因此android事件系统不会进一步传播事件。

因此,onClick永远不会生成事件,至少当我在事件处理程序中onClick返回时不会触发我的侦听器。另一方面,返回没有选项,因为这会阻止侦听器接收任何进一步的事件,这些事件是识别手势所必需的。解决这个问题的通常方法是什么?trueonTouchfalseonTouch

4

7 回答 7

8

在您的 GestureDetector 中,您可以直接调用 callOnClick()。注意 View.callOnClick API 需要 API 级别 15。试一试。

 // 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);
    }
}
于 2013-03-19T11:13:29.810 回答
6

如果你使用onTouchListener,你不必使用onClickListeneronClickListener它的作用是获取触摸事件并检查事件操作并检测点击。所以如果你想做一些工作的时候onClick。您可以onTouchListener通过过滤操作来做到这一点。

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;
}
于 2013-01-23T13:13:20.407 回答
4
@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;

    }
};
于 2015-04-07T13:40:49.483 回答
0
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;

另一种方法是使用线程。那就是在 Action_Down 上启动一个线程来增加一个计数器。在 Action_UP 的情况下:停止/中断线程。如果计数器小于 2(根据您的应用程序说或阈值)或 !isMove 然后调用 click 函数,则查找计数器

于 2014-09-24T18:11:45.013 回答
0

我们可以使用基于标志的实现。我们可以在 Action_Up 中处理滑动/拖动并使标志为真并返回相同的位置。如果单击或点击 Action_Down 中的相同句柄并将标志设置为 false 并返回。

touchAndSwipe=false;
switch(e.getAction()){
    case MotionEvent.ACTION_MOVE:
        break;
    case MotionEvent.ACTION_DOWN:
        x1 = e.getX();
        break;
    case MotionEvent.ACTION_UP:
        x2 = e.getX();
        float diff = x2 - x1;
        if(Math.abs(delta) > 100) {
            // Swipe
            touchAndSwipe = true;
        } else {
            touchAndSwipe = false;
        }
        break;
}
return touchAndSwipe;
于 2015-09-01T10:33:49.703 回答
0

我已经能够在我正在构建的自定义键盘中同时实现 OnClick 和 OnTouch。您可以查看此代码并根据您的上下文对其进行修改,因为您没有包含可供使用的代码示例。

如果您发布代码示例,我可以修改我的这个示例以实现相同的结果供您使用。当涉及到 Android 开发时,上下文就是一切。看看这个代码片段,看看它是否有帮助。否则发布您自己的示例,我将进行修改并回复。

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

这适用于 alpha 或数字输出类型的上下文,如果事件正在寻找发送或使用其他需要修改的上下文。

于 2017-03-03T17:54:22.883 回答
-1

我同意 jdx,如果您使用 onTouchlistener,则不需要使用 onclicklistener,反之亦然,如果您想触发按钮、图像或 textview 单击事件,则只需触发 onClicklistener。如果你想要一些动画,比如拖动和旋转,然后使用 ontouchlistener 来获取触摸表面的坐标

于 2013-01-23T13:21:42.220 回答