可移动自定义viewgroup--viewdraghelp心得

来源:互联网 发布:网络直播的利弊 编辑:程序博客网 时间:2024/05/18 00:52

最近项目需要一个可移动的viewgroup控件,这方面还是比较弱的(因为之前都没怎么做这个,而且网上的自定义控件文章很多,看了好久还是没有自信。我想还是没有彻底理解把,唉)在此感谢zhy大神,他的文章总是帮助好多。感谢大神,感谢开源精神。

SlidingPaneLayout和DrawerLayout这两个google的控件不知道大家有没有用过,据说都用到了viewdraghelper。因为我没有看过源码,只是听说。但是这已经说明了它的强大,不是吗?此处有‘赢笑’图片。为什么叫helper类呢,因为android手势处理还是比较复杂的,所以这个帮助类是帮助我们的快速实现的。

  • 创建实例(通过静态工厂方法创建的)
  • 触摸相关的方法的调用
  • ViewDragHelper.Callback实例的编写(大部分方法都在callback里面)
    开始自定义控件

  • 首先当然是继承RelativeLayout(布局viewgroup)

  • ViewDragHelper的初始化
  • ViewDragHelper.Callback
  • 触摸相关的方法的调用
    代码

初始化viewdraghelper

 /**         * 1.0f传入的值越大,越来越难拉         */        mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {

重写callback的方法
此方法决定哪个view可以滑动

/**             * tryCaptureView如果返回ture则表示可以捕获该view,你可以根据传入的第一个view参数决定哪些可以捕获             * @param child             * @param pointerId             * @return             */            @Override            public boolean tryCaptureView(View child, int pointerId) {                return child == mAutoBackView;//                return true;            }

设定左右上下滑动的范围

/**             * 设定左右上下滑动的范围             * @param child             * @param left             * @param dx             * @return             */            @Override            public int clampViewPositionHorizontal(View child, int left, int dx) {                return (getWidth() - mAutoBackView.getWidth())/2;            }            @Override            public int clampViewPositionVertical(View child, int top, int dy) {                int topBound = getPaddingTop();                int bottomBound = getHeight() - mBottomView.getHeight() - topBound - mAutoBackView.getHeight();                int newTop = Math.min(Math.max(top,topBound),bottomBound);                return newTop;            }

手指释放时调用的方法

/**             * 手指释放的时候回调             * @param releasedChild             * @param xvel             * @param yvel             */            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel) {                if (releasedChild == mAutoBackView) {//                    mAutoBackView.getScrollY()//                    Log.d("yzj------",""+mAutoBackView.getScrollY());//                    Log.d("yzj------","mAutoBackOriginPos.x:"+mAutoBackOriginPos.x+"mAutoBackOriginPos.y:"+mAutoBackOriginPos.y);                    mDragger.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y);                    invalidate();                    flag = false;                }                super.onViewReleased(releasedChild, xvel, yvel);            }

当在边缘滑动的时候调用

/**             * 在边缘滑动的时候调用             * @param edgeFlags             * @param pointerId             */            @Override            public void onEdgeTouched(int edgeFlags, int pointerId) {                super.onEdgeTouched(edgeFlags, pointerId);            }

view位置改变时调用

/**             * view位置改变时调用             * @param changedView             * @param left             * @param top             * @param dx             * @param dy             */            @Override            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {                super.onViewPositionChanged(changedView, left, top, dx, dy);                if(top == getHeight() - mBottomView.getHeight() - getPaddingTop() - mAutoBackView.getHeight() && (flag == false)){                    Log.d("yzj------","move to the most");                    flag = true;                }            }

接下来是触摸相关的方法的调用

@Override    public boolean onInterceptTouchEvent(MotionEvent event) {        return mDragger.shouldInterceptTouchEvent(event);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        mDragger.processTouchEvent(event);        return true;    }

layout完成时调用

/**     * 得到初始化位置     *     * @param changed     * @param l     * @param t     * @param r     * @param b     */    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        mAutoBackOriginPos.x = mAutoBackView.getLeft();        mAutoBackOriginPos.y = mAutoBackView.getTop();    }

完成inflate时的调用

@Override    protected void onFinishInflate() {        super.onFinishInflate();        mAutoBackView = getChildAt(1);        mBottomView = getChildAt(2);    }

通过以上几个方法的调用我相信能帮你实现很多的东西。最后放上全部的代码

public class VDRLayout extends RelativeLayout {    //helper类    private ViewDragHelper mDragger;    //回弹view    private View mAutoBackView;    //记录初始位置    private Point mAutoBackOriginPos = new Point();    private View mBottomView;    private boolean flag;    public VDRLayout(Context context, AttributeSet attrs) {        this(context, null, 0);    }    public VDRLayout(Context context) {        this(context, null);    }    public VDRLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        /**         * 1.0f传入的值越大,越来越难拉         */        mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {            /**             * tryCaptureView如果返回ture则表示可以捕获该view,你可以根据传入的第一个view参数决定哪些可以捕获             * @param child             * @param pointerId             * @return             */            @Override            public boolean tryCaptureView(View child, int pointerId) {                return child == mAutoBackView;//                return true;            }            /**             * 设定左右上下滑动的范围             * @param child             * @param left             * @param dx             * @return             */            @Override            public int clampViewPositionHorizontal(View child, int left, int dx) {                return (getWidth() - mAutoBackView.getWidth())/2;            }            @Override            public int clampViewPositionVertical(View child, int top, int dy) {                int topBound = getPaddingTop();                int bottomBound = getHeight() - mBottomView.getHeight() - topBound - mAutoBackView.getHeight();                int newTop = Math.min(Math.max(top,topBound),bottomBound);                return newTop;            }            /**             * 手指释放的时候回调             * @param releasedChild             * @param xvel             * @param yvel             */            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel) {                if (releasedChild == mAutoBackView) {//                    mAutoBackView.getScrollY()//                    Log.d("yzj------",""+mAutoBackView.getScrollY());//                    Log.d("yzj------","mAutoBackOriginPos.x:"+mAutoBackOriginPos.x+"mAutoBackOriginPos.y:"+mAutoBackOriginPos.y);                    mDragger.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y);                    invalidate();                    flag = false;                }                super.onViewReleased(releasedChild, xvel, yvel);            }            /**             * 在边缘滑动的时候调用             * @param edgeFlags             * @param pointerId             */            @Override            public void onEdgeTouched(int edgeFlags, int pointerId) {                super.onEdgeTouched(edgeFlags, pointerId);            }            /**             * view位置改变时调用             * @param changedView             * @param left             * @param top             * @param dx             * @param dy             */            @Override            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {                super.onViewPositionChanged(changedView, left, top, dx, dy);                if(top == getHeight() - mBottomView.getHeight() - getPaddingTop() - mAutoBackView.getHeight() && (flag == false)){                    Log.d("yzj------","move to the most");                    flag = true;                }            }        });        //允许哪个边缘可以调用        mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_BOTTOM);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        //决定我们是否应该拦截当前的事件        return mDragger.shouldInterceptTouchEvent(event);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        //处理事件        mDragger.processTouchEvent(event);        return true;    }    @Override    public void computeScroll() {        if (mDragger.continueSettling(true)) {            invalidate();        }    }    /**     * 得到初始化位置     *     * @param changed     * @param l     * @param t     * @param r     * @param b     */    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        mAutoBackOriginPos.x = mAutoBackView.getLeft();        mAutoBackOriginPos.y = mAutoBackView.getTop();    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mAutoBackView = getChildAt(1);        mBottomView = getChildAt(2);    }}
0 0
原创粉丝点击