android 用ViewDragHelper实现IOSAssistiveTouch小圆点(或者其他拖拉效果)

前言

用ViewDragHelper实现小圆点.
ViewDragHelper 拖动效果,对onInterceptTouchEvent onTouchEvent进行了封装,Android开发者可以不用深度去了解View的事件分发就特效拖拉的代码。包括侧滑删除、IOS小圆点。这里我分享一下AssistiveTouch的实现,废话不说,先效果 再代码。

效果:

大致效果如下

代码:

package com.steptowin.eshop.common.viewgroup;

import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import com.steptowin.library.base.app.LogStw;

/** 
 * Created by fjw on 2017/9/28.
 * [email protected]
 * http://blog.csdn.net/u011850446/article/details/78136299
 */

public class DragViewLayout extends FrameLayout {

    private View view_one;
    private ViewDragHelper mDragHelper;

    public DragViewLayout(Context context) {
        this(context, null);
    }

    public DragViewLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DragViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());
    }

    class DragHelperCallback extends ViewDragHelper.Callback {
        /**
         * 进行捕获拦截,那些View可以进行drag操作
         *
         * @param child
         * @param pointerId
         * @return 直接返回true,拦截所有的VIEW
         */
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return /*view_one == child*/true;
        }

        /**
         * 水平滑动 控制left
         *
         * @param child
         * @param left
         * @param dx
         * @return
         */
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            //LogStw.d("DragLayout", "clampViewPositionHorizontal " + left + "," + dx);
            final int leftBound = getPaddingLeft();
            final int rightBound = getWidth() - view_one.getWidth();
            final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
            return newLeft;
        }

        /**
         * 垂直滑动,控制top
         *
         * @param child
         * @param top
         * @param dy
         * @return
         */
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            LogStw.d("DragLayout", "clampViewPositionVertical " + top + "," + dy);
            final int topBound = getPaddingTop();
            final int bottomBound = getHeight() - view_one.getHeight();
            final int newTop = Math.min(Math.max(top, topBound), bottomBound);
            return newTop;
        }

        @Override
        public int getViewHorizontalDragRange(View child) {
            return getMeasuredWidth() - child.getMeasuredWidth();
        }

        @Override
        public int getViewVerticalDragRange(View child) {
            return getMeasuredHeight() - child.getMeasuredHeight();
        }

        /**
         * 当手指松开的时候回调方法
         *
         * @param xvel
         * @param yvel
         * @paramreleasedChild 滑动手指松开的View
         */
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            //LogStw.e("onViewReleased", ("getLeft:" + view_one.getLeft() + ", getTop=" + view_one.getTop()));
            float maxHeight = getHeight() - view_one.getHeight();
            float maxWidth = getWidth() - view_one.getWidth();
            float x = view_one.getLeft();
            float y = view_one.getTop();
            float diffx = maxWidth - x;
            float diffy = maxHeight - y;
            float min = Math.min(Math.min(Math.min(x, y), diffx), diffy);
            if (min == x)
                //左移动
                if (mDragHelper.smoothSlideViewTo(view_one, 0, (int) y)) {
                    ViewCompat.postInvalidateOnAnimation(DragViewLayout.this);
                }
            if (min == diffx)
                //右移动
                if (mDragHelper.smoothSlideViewTo(view_one, (int) maxWidth, (int) y)) {
                    ViewCompat.postInvalidateOnAnimation(DragViewLayout.this);
                }
            if (min == y)
                //上移动
                if (mDragHelper.smoothSlideViewTo(view_one, (int) x, 0)) {
                    ViewCompat.postInvalidateOnAnimation(DragViewLayout.this);
                }

            if (min == diffy)
                //下移动
                if (mDragHelper.smoothSlideViewTo(view_one, (int) x, (int) maxHeight)) {
                    ViewCompat.postInvalidateOnAnimation(DragViewLayout.this);
                }
            //离左轴的距离 x
            //离右轴的距离 maxRight - x
            //离顶轴的距离 y
            //离底轴的距离 winWidth - y
            //mDragHelper.smoothSlideViewTo(view_one, 0, 0);
            invalidate();
        }
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mDragHelper.continueSettling(true)) {
            invalidate();
        }
    }

    /**
     * 事件分发
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercept = mDragHelper.shouldInterceptTouchEvent(ev);
        //LogStw.e("intercept", String.valueOf(intercept));
        return intercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        mDragHelper.processTouchEvent(ev);
        return true;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        view_one = getChildAt(1);
    }
}

注意问题

  @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        view_one = getChildAt(1);//这里的1 对于你们来说不一定是1 
        // 可以传一个属性过来 说明是第几个Child是小圆点
    }

好了 完毕。

API介绍

 //固定写法   绑定this View与 ViewDragHelper工厂 ,不用理解
 mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());
 //固定写法   ViewDragHelper帮助处理 onInterceptTouchEvent  onTouchEvent,不用理解
   @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercept = mDragHelper.shouldInterceptTouchEvent(ev);
        //LogStw.e("intercept", String.valueOf(intercept));
        return intercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        mDragHelper.processTouchEvent(ev);
        return true;
    }
   //onFinishInflate这里去拿ChlidView
   protected void onFinishInflate() {
        super.onFinishInflate();
        view_one = getChildAt(1);
    }
    //固定写法  处理松手滚动效果 ,不用理解
    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mDragHelper.continueSettling(true)) {
            invalidate();
        }
    }
    //松手回调   **关键代码**  这里看情况处理  配合打印日志理解 最终算出效果
    onViewReleased
    //当View有点击事件的时候需要添加 不用理解。  
     @Override
        public int getViewHorizontalDragRange(View child) {
            return getMeasuredWidth() - child.getMeasuredWidth();
        }

        @Override
        public int getViewVerticalDragRange(View child) {
            return getMeasuredHeight() - child.getMeasuredHeight();
        }
        //控制滑动范围的两个方法 如果没有滑动范围要求按如下填写,**最好理解**。  
         /**
         * 水平滑动 控制left
         *
         * @param child
         * @param left
         * @param dx
         * @return
         */
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            //LogStw.d("DragLayout", "clampViewPositionHorizontal " + left + "," + dx);
            final int leftBound = getPaddingLeft();
            final int rightBound = getWidth() - view_one.getWidth();
            final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
            return newLeft;
        }

        /**
         * 垂直滑动,控制top
         *
         * @param child
         * @param top
         * @param dy
         * @return
         */
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            LogStw.d("DragLayout", "clampViewPositionVertical " + top + "," + dy);
            final int topBound = getPaddingTop();
            final int bottomBound = getHeight() - view_one.getHeight();
            final int newTop = Math.min(Math.max(top, topBound), bottomBound);
            return newTop;
        }
    配合onFinishInflate 使用判断那些View可以进行拖拉操作
    /**
         * 进行捕获拦截,那些View可以进行drag操作
         *
         * @param child
         * @param pointerId
         * @return 直接返回true,拦截所有的VIEW
         */
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return /*view_one == child*/true;
        }

总结

除了上面不用理解的,需要理解的就是onFinishInflate、tryCaptureView、onViewReleased三个方法了。Copy这份代码然后在这几个方法上改动就能写出大部分Viewgroup拖拉效果了。是不是很心动,快去试试吧。转载来自http://blog.csdn.net/u011850446/article/details/78136299

猜你喜欢

转载自blog.csdn.net/u011850446/article/details/78136299
今日推荐