拖拽<三>

使用ViewDragHelper实现拖拽<二>的布局拖拽效果。

官方在v4的支持包中提供了ViewDragHelper这样一个类来帮助我们方便的编写自定义ViewGroup。
    ViewDragHelper.Callback是连接ViewDragHelper与view之间的桥梁;
    ViewDragHelper的实例是通过静态工厂方法创建的;
    ViewDragHelper可以检测到是否触及到边缘;
    ViewDragHelper并不是直接作用于要被拖动的View,而是使其控制的视图容器中的子View可以被拖动,如果要指定某个子view的行为,需要在Callback中实现;
    ViewDragHelper的本质其实是分析onInterceptTouchEvent和onTouchEvent的MotionEvent参数,然后根据分析的结果去改变一个容器中被拖动子View的位置。

ViewDragHelper 提供了两个工厂方法来创建实例:
    static ViewDragHelper   create(ViewGroup forParent, float sensitivity, ViewDragHelper.Callback cb)
    static ViewDragHelper   create(ViewGroup forParent, ViewDragHelper.Callback cb)
    参数:
        ViewGroup:与ViewDragHelper相关联ViewGroup
        sensitivity:拖拽灵敏系数
        cb:ViewDragHelper.Callback的回调类型之一。


ViewDragHelper提供的全部回调方法:
    int            clampViewPositionHorizontal(View child, int left, int dx)
    int            clampViewPositionVertical(View child, int top, int dy)
    int            getOrderedChildIndex(int index)
    int            getViewHorizontalDragRange(View child)
    int            getViewVerticalDragRange(View child)
    void            onEdgeDragStarted(int edgeFlags, int pointerId)
    boolean        onEdgeLock(int edgeFlags)
    void            onEdgeTouched(int edgeFlags, int pointerId)
    void            onViewCaptured(View capturedChild, int activePointerId)
    void            onViewDragStateChanged(int state)
    void            onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
    void            onViewReleased(View releasedChild, float xvel, float yvel)
abstract boolean    tryCaptureView(View child, int pointerId)


ViewDragHelper 回调中能构成最简单能运行实例的方法:
    // 决定了是否需要捕获这个 child,只有捕获了才能进行下面的拖拽行为
    abstract boolean    tryCaptureView(View child, int pointerId)  

    // 修整 child 水平方向上的坐标,left 指 child 要移动到的坐标,dx 相对上次的偏移量
    int clampViewPositionHorizontal(View child, int left, int dx)

    // 修整 child 垂直方向上的坐标,top 指 child 要移动到的坐标,dy 相对上次的偏移量
    int clampViewPositionVertical(View child, int top, int dy)

    // 手指释放时的回调
    void    onViewReleased(View releasedChild, float xvel, float yvel)
    
    
要用 ViewDragHelper 来处理拖拽这个流程,自然要把触摸相关的动作要委托给它了
这就涉及到了 ViewDrageHelper 两个方法:

/** 是否应该拦截 children 的触摸事件,
*只有拦截了 ViewDragHelper 才能进行后续的动作
*将它放在 ViewGroup 中的 onInterceptTouchEvent() 方法中就好了
**/
boolean shouldInterceptTouchEvent(MotionEvent ev)


/** 处理 ViewGroup 中传递过来的触摸事件序列
*在 ViewGroup 中的 onTouchEvent() 方法中处理
*/
void    processTouchEvent(MotionEvent ev)

简单实现:

package com.hjk.shiny.androidcontrols;

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

/**
 * Created by Maibenben on 2018/2/2.
 */

public class DragViewHelper extends FrameLayout{

    private ViewDragHelper mHelper;

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

    public DragViewHelper(Context context, @Nullable AttributeSet attrs) {
        this(context,attrs,0);
    }

    public DragViewHelper(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


        mHelper=ViewDragHelper.create(this, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return true;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                return left;
            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                return top;
            }

            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
            }
        });
    }

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

        return true;
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {



        return mHelper.shouldInterceptTouchEvent(ev);
    }
}
初步实现很简单,但真正精通还需要仔细研究研究才是。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值