美文网首页
GridView的Item按下后纵向滑动收不到ACTION_UP

GridView的Item按下后纵向滑动收不到ACTION_UP

作者: _年少 | 来源:发表于2018-05-31 10:42 被阅读0次

    需求是 GridView的Item按下后放大 松手时缩放至原来大小 所以很简单的想到在onTouchEvent方法的 ACTION_DOWNACTION_DOWN 动作中添加相应的代码

    @Override
        public boolean onTouchEvent(MotionEvent event) {
            ObjectAnimator scaleX;
            ObjectAnimator scaleY;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //组合动画
                    mAnimator.end();
                    scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1.1f);
                    scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1.1f);
                    mAnimator.setDuration(100);
                    mAnimator.setInterpolator(new DecelerateInterpolator());
                    mAnimator.play(scaleX).with(scaleY);//两个动画同时开始
                    mAnimator.start();
                    break;
                case MotionEvent.ACTION_UP:
                    mAnimator.end();
                    scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1f);
                    scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1f);
                    mAnimator.setDuration(100);
                    mAnimator.setInterpolator(new DecelerateInterpolator());
                    mAnimator.play(scaleX).with(scaleY);//两个动画同时开始
                    mAnimator.start();
                    break;
            }
            return super.onTouchEvent(event);
        }
    

    本以为两段代码的事情 运行到设备后发现两段代码还是不够

    image.png
    正常点击后松开Item可以执行到ACTION_DOWNACTION_UP动作 但是当按下后上下滑动就只能执行到ACTION_DOWN动作结果就是如图中Item无法缩放至原始大小

    既然执行了ACTION_UP没有执行ACTION_DOWN所以猜测是触摸事件被父控件的onInterceptTouchEvent方法给拦截 则在代码中添加ACTION_CANCEL动作代码

    case MotionEvent.ACTION_CANCEL:
                    mAnimator.end();
                    scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1f);
                    scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1f);
                    mAnimator.setDuration(100);
                    mAnimator.setInterpolator(new DecelerateInterpolator());
                    mAnimator.play(scaleX).with(scaleY);//两个动画同时开始
                    mAnimator.start();
                    //按钮弹起逻辑
                    break;
    

    问题解决

    然后猜测是触摸事件被父控件的onInterceptTouchEvent方法给拦截 查代码证实下

    image.png
    先找到GridView中没有onInterceptTouchEvent方法,点击进入父类AbsListView中继续查看
    image.png
    从方法列表中找出onInterceptTouchEvent方法的ACTION_MOVE动作,代码如下
            case MotionEvent.ACTION_MOVE: {
                switch (mTouchMode) {
                case TOUCH_MODE_DOWN:
                    int pointerIndex = ev.findPointerIndex(mActivePointerId);
                    if (pointerIndex == -1) {
                        pointerIndex = 0;
                        mActivePointerId = ev.getPointerId(pointerIndex);
                    }
                    final int y = (int) ev.getY(pointerIndex);
                    initVelocityTrackerIfNotExists();
                    mVelocityTracker.addMovement(ev);
                    if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) {
                        return true;
                    }
                    break;
                }
                break;
            }
    

    代码中看出 如果startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)返回true则拦截事件,点击找到startScrollIfNeeded代码如下

    private boolean startScrollIfNeeded(int x, int y, MotionEvent vtev) {
            // Check if we have moved far enough that it looks more like a
            // scroll than a tap
            final int deltaY = y - mMotionY;
            final int distance = Math.abs(deltaY);
            final boolean overscroll = mScrollY != 0;
            if ((overscroll || distance > mTouchSlop) &&
                    (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) {
                createScrollingCache();
                if (overscroll) {
                    mTouchMode = TOUCH_MODE_OVERSCROLL;
                    mMotionCorrection = 0;
                } else {
                    mTouchMode = TOUCH_MODE_SCROLL;
                    mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop;
                }
                removeCallbacks(mPendingCheckForLongPress);
                setPressed(false);
                final View motionView = getChildAt(mMotionPosition - mFirstPosition);
                if (motionView != null) {
                    motionView.setPressed(false);
                }
                reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                // Time to start stealing events! Once we've stolen them, don't let anyone
                // steal from us
                final ViewParent parent = getParent();
                if (parent != null) {
                    parent.requestDisallowInterceptTouchEvent(true);
                }
                scrollIfNeeded(x, y, vtev);
                return true;
            }
    
            return false;
        }
    

    从方法中可以看出GridView是结束滑动的并且滑动方向是纵向则返回true

    if ((overscroll || distance > mTouchSlop) &&
                    (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) 
    

    工作好几年 一直没怎么有写东西的习惯,所以对写东西也越来越生疏,改变总是痛苦的,但改变也是必要的
    以后会养成写东西 记东西的习惯 记下自己以前 现在 以后在开发中遇到的问题

    相关文章

      网友评论

          本文标题:GridView的Item按下后纵向滑动收不到ACTION_UP

          本文链接:https://www.haomeiwen.com/subject/yrnfsftx.html