ViewDragHelper 的简单使用(实现侧边栏滑动效果)

拖拽滑动效果如下:

这里写图片描述
主Activity:onCreate中

setContentView(R.layout.activity_main);

布局:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<com.android.myapplication.DragViewGroup
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/menu_layout"
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:text="menu"/>
    <TextView
        android:id="@+id/main_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/darker_gray"/>
</com.android.myapplication.DragViewGroup>

ViewDragHelper的相关代码如下。

package com.android.myapplication;

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

/**
 * Top Secret, Copyright (C) TRANSSION HOLDINGS.
 * Any fragment herein  shall not be copied, saved, quoted or spread without TRANSSION HOLDINGS' written authorization.
 *
 * @class describe
 */

public class DragViewGroup extends FrameLayout {
    public DragViewGroup(Context context) {
        super(context, null);
        initView();
    }

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

    public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initView();
    }

    private ViewDragHelper mViewDragHelper;

    public void initView() {
        if (mViewDragHelper != null) {
            return;
        }
        /**
         * ViewDragHelper 通常定义在一个ViewGroup的内部,并通过其静态工厂方法进行初始化。
         *它的第一个参数是要监听的View,通常需要是一个ViewGroup,即parentView;第二个参数是一个Callback 回调,这个回调就是整个ViewDragHelp的逻辑核心
         */
        mViewDragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
            /**
             * 通过这个方法,我们可以指定在创建ViewDragHelper时,参数parentView中的哪个子View可以被移动,
             * 例如这个实例中自定义了一个ViewGroup,里面定义了两个 子View(menuView mainView),
             * 当指定如下代码时,则只有MainView是可以被拖动的。
             * @param child
             * @param pointerId
             * @return
             */
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                //若果当前触摸的child是mMainView时开始检测
                return child == mMainView;
            }

            /**
             * 水平方向的滑动。默认返回值是0,即不发生滑动。
             * @param child
             * @param left 水平方向上child移动的距离。
             * @param dx 比较前一次的增量
             * @return
             */
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                Log.i("wlj", "left === " + left + " dx = " + dx);
                if (left > 0) {

                    return Math.min(left, mMenuViewWidth);
                }
                return 0;
            }

            /**
             * 垂直方向的滑动,默认返回值是0,即不发生滑动。
             * @param child
             * @param top 垂直方向上child移动的距离
             * @param dy 比较前一次的增量
             * @return
             */
            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                return 0;
            }

            /**
             * 拖拽结束时调用
             * 当然,这个方法内部是通过Scroller来实现的,这也是需要重写computeScroll()方法的原因。
             * @param releasedChild
             * @param xvel
             * @param yvel
             */
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                //手指抬起后缓慢移动到指定位置
                if (mMainView.getLeft() < 300) {
                    //关闭菜单,相当于Scroller的startScroll方法
                    mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
                    ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                } else {
                    //打开菜单
                    mViewDragHelper.smoothSlideViewTo(mMainView, mMenuViewWidth, 0);
                    ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
                }
            }
        });
    }

    View mMainView;
    View mMenuView;
    int mMenuViewWidth = 0;

    /**
     * 加载完布局文件后调用
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mMenuView = getChildAt(0);
        mMainView = getChildAt(1);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //获取View的宽度,(需要根据View的宽度来处理滑动后的效果)
        mMenuViewWidth = mMenuView.getMeasuredWidth();
    }

    /**
     * 重写事件拦截方法,将事件传给ViewDragHelper进行处理
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /**将触摸事件传递给ViewDragHelper,此操作必不可少
         */
        mViewDragHelper.processTouchEvent(event);
        return true;
    }

    /**
     * ViewDragHelper 同样需要重写下ComputeScroll()方法,因为ViewDragHelper内部也是通过Scroller来实现平滑移动的。
     * 通常情况下,可以使用如下所示的模块代码
     */
    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mViewDragHelper != null && mViewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }
}

ViewDragHelper 的很多强大的功能还没能够得到展示,在ViewDragHelper.Callnack 中,系统定义了大量的监听事件来帮助我们处理各种事件,下面就列举一些事件。
1.onViewCaptured():这个事件在用户触摸到View后调用。
2.onViewDragStateChanged():这个事件在拖拽状态改变时回调。比如idle,dragging 等状态
3.onViewPositionChanged():这个事件在位置改变时回调,常用于滑动时更改Scale等进行缩放等效果。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值