【问题标题】:Handling Touch Events - onInterceptTouchEvent and onTouchEvent处理触摸事件 - onInterceptTouchEvent 和 onTouchEvent
【发布时间】:2015-02-08 22:42:55
【问题描述】:

我希望能够在屏幕上的任意位置滑动来调用某个函数。但我在Linear Layouts 中也有Buttons,我希望能够点击它。如果我在Button 上滑动,我希望onInterceptTouchEvent 到Intercept 调用Button 的onTouchEvent 并执行滑动操作。如果我只是单击Button,我不想调用onInterceptTouchEvent。相反,我希望调用Button 的onTouchEvent 并执行Button click

但是当我尝试实现onInterceptTouchEvent 时出现错误。

这是我的代码:

public class Game extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.game_activity);

   //other code....
}
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            swipeScreen(); //if action recognized as swipe then swipe
            break;
        case MotionEvent.ACTION_MOVE:
            float x = event.getX();
            float y = event.getY();
            float xDelta = Math.abs(x - mLastX);
            float yDelta = Math.abs(y - mLastY);

            if (yDelta > xDelta) {
                return true;
            }
            break;
    }

    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    ButtonOnClick(); //if not a swipe, then button click
    return true;
}

首先错误显示:The method onInterceptTouchEvent(MotionEvent) of type Game must override or implement a supertype method

然后,我将代码更改为:return super.onInterceptTouchEvent(event),而不是 return true,但随后出现错误消息:The method onInterceptTouchEvent(MotionEvent) is undefined for the type Activity

有人可以帮忙吗?

【问题讨论】:

  • onInterceptTouchEvent() 方法是ViewGroup 类的成员。要实现它,您必须继承 ViewGroup 以在您的布局中使用。
  • hm,那么我如何子类化我的视图组? - 对不起,我只是 android 的新手
  • 感谢我掌握了窍门

标签: android onclick touch touch-event


【解决方案1】:

我使用 fernandohur 方法(阅读他的 post),这种方法非常可重复使用、自给自足,并提供检测任何方向的滑动所需的一切。

要使用 fernandohur onSwipeListener,请按照以下简单步骤操作。所有代码都是用 Kotlin 编写的:

// 1) Add his onSwipeListener to the project. Credits should go to him

// 2) Implement an anonymous class for the swipe listener:
val onSwipeListener: OnSwipeListener = object : OnSwipeListener() {
    override fun onSwipe(direction: Direction): Boolean {

        if (direction == Direction.Up) {
            //do somethin
            return true
        } else if (direction == Direction.Down) {
            //do something else
            return true
        }
        return super.onSwipe(direction)
    }
}

// 3) connect the listener to the view
val mDetector = GestureDetectorCompat(this.context, onSwipeListener)

// 4) route the touch events to the listener
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
    return if (this.mDetector!!.onTouchEvent(event)) {
        true
    } else super.onInterceptTouchEvent(event)
}

【讨论】:

    【解决方案2】:

    请注意,onInterceptTouchEvent() 是来自 ViewGroup 类的方法,而不是来自 Activity。

    您可以通过将您的逻辑从onInterceptTouchEvent() 移动到dispatchTouchEvent(MotionEvent ev) 来实现所需的行为。记得调用dispatchTouchEvent(MotionEvent ev)的超类实现来处理应该正常处理的事件。

    还请注意,只有当增量大于system constant for touch slop 时,您才应将移动视为滑动。我建议通过测试yDelta / 2 > xDelta 而不是yDelta > xDelta,确保用户朝你想要的方向滑动。

    public class Game extends Activity {
        private int mSlop;
        private float mDownX;
        private float mDownY;
        private boolean mSwiping;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.game_activity);
    
            ViewConfiguration vc = ViewConfiguration.get(this)
            mSlop = vc.getScaledTouchSlop();
    
           //other code....
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mDownX = ev.getX();
                    mDownY = ev.getY();
                    mSwiping = false;
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    if(mSwiping) {
                        swipeScreen(); //if action recognized as swipe then swipe
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    float x = ev.getX();
                    float y = ev.getY();
                    float xDelta = Math.abs(x - mDownX);
                    float yDelta = Math.abs(y - mDownY);
    
                    if (yDelta > mSlop && yDelta / 2 > xDelta) {
                        mSwiping = true;
                        return true;
                    }
                    break;
            }
    
            return super.dispatchTouchEvent(ev);
        }
    }
    

    【讨论】:

    • 反之如何?我只想点击事件而不是滑动事件
    猜你喜欢
    • 1970-01-01
    • 2012-10-26
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多