ViewDragHelper理解

<code>public class ViewDragHelper extends Object
java.lang.Object

android.support.v4.widget.ViewDragHelper</code>


ViewDragHelper是什么?

官方的解释:

ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number of useful operations and state tracking for allowing a user to drag and reposition views within their parent ViewGroup.

ViewDragHelper是编写自定义ViewGroups一个实用工具类。

它定义了一组有用的操作和状态追踪,允许用户在父ViewGroup中拖动并且重新定位子View(child view)。

<ol>
<li>ViewDragHelper.Callback是连接ViewDragHelper与view之间的桥梁(这个view一般是指拥子view的容器即parentView);</li>
<li> ViewDragHelper的实例是通过静态工厂方法创建的;</li>
<li>能够指定拖动的方向;</li>
<li> ViewDragHelper可以检测到是否触及到边缘;</li>
<li> ViewDragHelper并不是直接作用于要被拖动的View,而是使其控制的视图容器中的子View可以被拖动,如果要指定某个子view的行为,需要在Callback中想办法;</li>
<li> ViewDragHelper的本质其实是分析onInterceptTouchEvent和onTouchEvent的MotionEvent参数,然后根据分析的结果去改变一个容器中被拖动子View的位置( 通过offsetTopAndBottom(int offset)和offsetLeftAndRight(int offset)方法 ),他能在触摸的时候判断当前拖动的是哪个子View;</li>
<li>ViewDragHelper的实例方法 ViewDragHelper create(ViewGroup forParent, Callback cb) 可以指定一个被ViewDragHelper处理拖动事件的对象 。</li>
</ol>

ViewDragHelper.Callback(ViewDragHelper与View之间的桥梁)

<code>public static abstract class ViewDragHelper.Callback
extends Object
java.lang.Object

android.support.v4.widget.ViewDragHelper.Callback</code>

官网简介:

A Callback is used as a communication channel with the ViewDragHelper back to the parent view using it. on*
methods are invoked on significant events and several accessor methods are expected to provide the ViewDragHelper with more information about the state of the parent view upon request. The callback also makes decisions governing the range and draggability of child views.

Callback是连接ViewDragHelper与parentView之间的桥梁。
方法在重要的事件中被调用,几个访问方法会提供给ViewDragHelper更多关于parentView的状态信息。
Callback同时也决定了拖动的范围和子view的拖动能力。

<br />

为什么要使用ViewDragHelper

ViewDragHelper解决了android中手势处理过于复杂的问题,在DrawerLayout出现之前,侧滑菜单都是由第三方开源代码实现的,其中著名的当属 MenuDrawer ,MenuDrawer重写onTouchEvent方法来实现侧滑效果,代码量很大,实现逻辑也需要很大的耐心才能看懂。如果每个开发人员都从这么原始的步奏开始做起,那对于安卓生态是相当不利的。所以说ViewDragHelper等的出现反映了安卓开发框架已经开始向成熟的方向迈进。

ViewDragHelper实例

根据开源项目android-card-slide-panel 简化

创建自定义的ViewGroup

public class CardSlidePanel extends ViewGroup {


    private ViewDragHelper mViewDragHelper;

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

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

    public CardSlidePanel(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 滑动相关类
        mViewDragHelper = ViewDragHelper
                .create(this, 10f, new DragHelperCallback());
        mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
        int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(
                resolveSizeAndState(maxWidth, widthMeasureSpec, 0),
                resolveSizeAndState(maxHeight, heightMeasureSpec, 0));
    }

    @Override
    protected void onLayout(boolean changed, int left, int t, int right, int b) {
        int mTotalHeight = 0;

        // 遍历所有子视图
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);

            // 获取在onMeasure中计算的视图尺寸
            int measureHeight = childView.getMeasuredHeight();
            int measuredWidth = childView.getMeasuredWidth();

            childView.layout(left, mTotalHeight, measuredWidth, mTotalHeight + measureHeight);

            mTotalHeight += measureHeight;

        }
    }

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



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

    /**
     * 这是viewdraghelper拖拽效果的主要逻辑
     */
    private class DragHelperCallback extends ViewDragHelper.Callback {

        @Override
        public void onViewPositionChanged(View changedView, int left, int top,
                                          int dx, int dy) {
        }

        @Override
        public boolean tryCaptureView(View child, int pointerId) {

            return true;
        }

        @Override
        public int getViewHorizontalDragRange(View child) {
            return 256;
        }

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

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

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


}

创建布局文件layout_drag.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:orientation="vertical">


    <org.lethisis.weather.weatherl.ui.widget.cardslide.CardSlidePanel
        android:id="@+id/image_slide_panel"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimaryDark">


        <LinearLayout
            android:id="@+id/card_bottom_layout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <Button
                android:id="@+id/card_left_btn"
                android:layout_width="70dp"
                android:layout_height="70dp" />

            <Button
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="10dp" />

            <Button
                android:id="@+id/card_right_btn"
                android:layout_width="70dp"
                android:layout_height="70dp"
                android:layout_marginLeft="10dp" />
        </LinearLayout>

        <org.lethisis.weather.weatherl.ui.widget.cardslide.CardItemView
            android:layout_width="@dimen/card_image_width"
            android:layout_height="100dp" />

        <org.lethisis.weather.weatherl.ui.widget.cardslide.CardItemView
            android:layout_width="@dimen/card_image_width"
            android:layout_height="100dp" />

        <org.lethisis.weather.weatherl.ui.widget.cardslide.CardItemView
            android:layout_width="@dimen/card_image_width"
            android:layout_height="wrap_content" />

        <org.lethisis.weather.weatherl.ui.widget.cardslide.CardItemView
            android:layout_width="@dimen/card_image_width"
            android:layout_height="wrap_content" />


    </org.lethisis.weather.weatherl.ui.widget.cardslide.CardSlidePanel>

</LinearLayout>

【待续】

参考:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0911/1680.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,235评论 25 709
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,758评论 2 45
  • 《鞋狗》:耐克这样实现从0到1音频 本书是耐克的创始人菲尔·奈特首度批披露他的创业历程,去年一经面世,便荣登了20...
    读到阅读 2,472评论 0 0
  • 除夕那晚 我梦见了你 我们是否都爱 了解自己更深的人 我们是否都怕 自己深爱的人 于是我一直 努力变成你不懂的样子...
    纪加阅读 1,346评论 0 0
  • 得: 1.最值得开心的,一定是获得了签证,依靠自信,运气,机智,爸妈全力配合获得的好结果。 2.见到了一直想念的朋...
    黄童彤阅读 1,094评论 0 0

友情链接更多精彩内容