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一個實用工具類。

它定義了一組有用的操作和狀態(tài)追蹤,允許用戶在父ViewGroup中拖動并且重新定位子View(child view)。

<ol>
<li>ViewDragHelper.Callback是連接ViewDragHelper與view之間的橋梁(這個view一般是指擁子view的容器即parentView);</li>
<li> ViewDragHelper的實例是通過靜態(tài)工廠方法創(chuàng)建的;</li>
<li>能夠指定拖動的方向;</li>
<li> ViewDragHelper可以檢測到是否觸及到邊緣;</li>
<li> ViewDragHelper并不是直接作用于要被拖動的View,而是使其控制的視圖容器中的子View可以被拖動,如果要指定某個子view的行為,需要在Callback中想辦法;</li>
<li> ViewDragHelper的本質(zhì)其實是分析onInterceptTouchEvent和onTouchEvent的MotionEvent參數(shù),然后根據(jù)分析的結(jié)果去改變一個容器中被拖動子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>

官網(wǎng)簡介:

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之間的橋梁。
方法在重要的事件中被調(diào)用,幾個訪問方法會提供給ViewDragHelper更多關(guān)于parentView的狀態(tài)信息。
Callback同時也決定了拖動的范圍和子view的拖動能力。

<br />

為什么要使用ViewDragHelper

ViewDragHelper解決了android中手勢處理過于復雜的問題,在DrawerLayout出現(xiàn)之前,側(cè)滑菜單都是由第三方開源代碼實現(xiàn)的,其中著名的當屬 MenuDrawer ,MenuDrawer重寫onTouchEvent方法來實現(xiàn)側(cè)滑效果,代碼量很大,實現(xiàn)邏輯也需要很大的耐心才能看懂。如果每個開發(fā)人員都從這么原始的步奏開始做起,那對于安卓生態(tài)是相當不利的。所以說ViewDragHelper等的出現(xiàn)反映了安卓開發(fā)框架已經(jīng)開始向成熟的方向邁進。

ViewDragHelper實例

根據(jù)開源項目android-card-slide-panel 簡化

創(chuàng)建自定義的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);
        // 滑動相關(guān)類
        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;
        }
    }


}

創(chuàng)建布局文件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>

【待續(xù)】

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,094評論 25 709
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,877評論 2 45
  • 《鞋狗》:耐克這樣實現(xiàn)從0到1音頻 本書是耐克的創(chuàng)始人菲爾·奈特首度批披露他的創(chuàng)業(yè)歷程,去年一經(jīng)面世,便榮登了20...
    讀到閱讀 351評論 0 0
  • 除夕那晚 我夢見了你 我們是否都愛 了解自己更深的人 我們是否都怕 自己深愛的人 于是我一直 努力變成你不懂的樣子...
    紀加閱讀 212評論 0 0
  • 得: 1.最值得開心的,一定是獲得了簽證,依靠自信,運氣,機智,爸媽全力配合獲得的好結(jié)果。 2.見到了一直想念的朋...
    黃童彤閱讀 140評論 0 0

友情鏈接更多精彩內(nèi)容