Android滑动删除控件

Android滑动删除控件

效果展示

代码实现

静态布局

自定义一个ViewGroup,继承至FrameLayout,覆写其中的几个关键方法,用于给其中的两个子view设置布局位置。


    private View contentView, deleteView;
    int contentViewHeight, contentViewWidth;
    int deleteViewHeight, deleteViewWidth;

    private void init() {
    }


    /**
     * 从xml中加载完布局,只知道有几个子view,并没有进行测量
     * 一般可以初始化子view的引用
     */
    @Override
    protected void onFinishInflate() {
    super.onFinishInflate();
    contentView = getChildAt(0);
    deleteView = getChildAt(1);
    }

    /**
     * 测量完子view后调用,在这里可以直接获取子view的高度
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    contentViewWidth = contentView.getMeasuredWidth();
    deleteViewHeight = deleteView.getMeasuredHeight();
    }


    /**
     * 放置子view到合适的位置
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    contentView.layout(0, 0, contentViewWidth, contentViewHeight);
    deleteView.layout(contentViewWidth, 0, contentViewWidth + deleteViewWidth,  deleteViewHeight);
    }

处理滑动逻辑

利用ViewDragHelper类封装了对触摸位置、速度、距离的检测,以及Scroller.
需要我们制定什么时候滑动,以及滑动多少。
需要把ViewGroup中受到的触摸事件传给ViewDragHelper实例。

触摸事件传给ViewDragHelper实例

       @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);

        //消费掉此触摸事件,不向上返回
        return true;
    }
在ViewDragHelper的回调函数中处理滑动逻辑。

    private ViewDragHelper mViewDragHelper;
    private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

        /**
         * @return 返回true表示获得view的控制权
         */
        @Override
        public boolean tryCaptureView(View view, int i) {
            return view == contentView || view == deleteView;
        }

        @Override
        public void onViewCaptured(View capturedChild, int activePointerId) {
            super.onViewCaptured(capturedChild, activePointerId);
        }

        /**
         * 控制view在水平方向上实际滑动了多少
         * @param child 当前触摸的view
         * @param left view的左边坐标,负数表示view的左边超出父view边界的长度
         * @param dx
         * @return 返回多少,代表想让child的left=多少
         */
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            Log.i(TAG, "clampViewPositionHorizontal-->" + "left=" + left);
            if (child == contentView) {
                if (left > 0) left = 0;
                if (left < -deleteViewWidth) left = -deleteViewWidth;
            } else if (child == deleteView) {
                //使deleteVie不会超出指定的边界
                if (left < contentViewWidth - deleteViewWidth) {
                    left = contentViewWidth - deleteViewWidth;
                }
            }
            return left;
        }

        /**
         * 水平方向拖拽的范围
         */
        @Override
        public int getViewHorizontalDragRange(View child) {
            return super.getViewHorizontalDragRange(child);
        }

        /**
         * view滑动后的回调
         * @param changedView
         * @param left
         * @param top
         * @param dx   x轴方向的改编值
         * @param dy
         */
        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);
            Log.i(TAG, "onViewPositionChanged-->" + "dx=" + dx);
            //重新布局子view的位置
            if (changedView == contentView) {
                deleteView.layout(deleteView.getLeft() + dx, 0, deleteView.getRight() + dx, deleteView.getBottom());
            } else if (changedView == deleteView) {
                contentView.layout(contentView.getLeft() + dx, 0, contentView.getRight() + dx, contentView.getBottom());
            }
        }

        /**
         * TouchUp的回调
         * @param releasedChild
         * @param xvel
         * @param yvel
         */
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);

            if (contentView.getLeft() < -deleteViewWidth / 2) {   //滑动条打开状态
                mViewDragHelper.smoothSlideViewTo(contentView, -deleteViewWidth, 0);
            } else {          //滑动条关闭状态
                mViewDragHelper.smoothSlideViewTo(contentView, 0, 0);
            }
            //
            ViewCompat.postInvalidateOnAnimation(SwipeView.this);  //动画刷新
        }
    };
动画效果

Scroller帮助计算好view在某个时间点会处于某个位置,达到动画的效果


    @Override
    public void computeScroll() {
        super.computeScroll();
        if(mViewDragHelper.continueSettling(true)){     //内部有Scroller计算位置和移动
            ViewCompat.postInvalidateOnAnimation(SwipeView.this);       //刷新当前view
        }

    }

ListView中的滑动删除效果

完整代码

github

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值