ViewDragHelper制作底部弹出菜单

来源:互联网 发布:外星人源码站 编辑:程序博客网 时间:2024/04/28 18:17

周日难得清闲,遂在网上闲逛。突然发现 Android Support Library 23.2里面多了一个Bottom Sheets—-WOW。感觉蛮不错的,越来越方便了。难耐心中有些不甘,所以正好利用最近学到的ViewDragHelper来仿制一个底部弹出的菜单。

1.首先感谢谷歌大法中的Drawerlayout
2.然后感谢鸿翔老师的精品博客 http://blog.csdn.net/hongxiang_ecjtu(目测刚结婚了)

话不多说先上图 PS:家里电脑太烂了,连虚拟机都跑不起来,录不成gif。各位看管老爷见谅

然后上代码

package com.ggq.viewdraghelperdemo;import android.content.Context;import android.support.v4.widget.DrawerLayout;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;/** * Created by DYK on 2016/3/20. */public class MyGroupView extends ViewGroup {    private static final int MIN_FLING_VELOCITY = 100;    private View bottomMenuView;    private View mContentView;    private ViewDragHelper mHelper;    private DrawerLayout d;    public MyGroupView(Context context, AttributeSet attrs)    {        super(context, attrs);        final float density = getResources().getDisplayMetrics().density;        final float minVel = MIN_FLING_VELOCITY * density;        mHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback()        {            @Override            public int clampViewPositionHorizontal(View child, int left, int dx)            {                //左右只能在父布局之内滑动                final int leftBound = getPaddingLeft();                final int rightBound = getWidth() - child.getWidth() - leftBound;                final int newLeft = Math.min(Math.max(left, leftBound), rightBound);                return newLeft;            }            @Override            public int clampViewPositionVertical(View child, int top, int dy) {                //底部菜单滑动只能是自己的高度                if(child==bottomMenuView)                {                    final int topBound=getHeight()-child.getHeight();                    final int bottomBound=getHeight();                    final int newtop=Math.min(Math.max(top,topBound),bottomBound);                    return newtop;                }                return top;            }            @Override            public boolean tryCaptureView(View child, int pointerId)            {                return child==bottomMenuView;            }            @Override            public void onEdgeDragStarted(int edgeFlags, int pointerId)            {                mHelper.captureChildView(bottomMenuView, pointerId);            }            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel)            {                final int childHeight = releasedChild.getHeight();                float offset = (getHeight()- releasedChild.getTop()) * 1.0f / childHeight;                System.out.println("offset"+offset+"   yvel"+yvel);                if(yvel < 0||offset>0.5f)                {                    mHelper.settleCapturedViewAt(0,  getHeight()-releasedChild.getHeight());                }                else                {                    mHelper.settleCapturedViewAt(0,  getHeight());                }                invalidate();            }            @Override            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)            {                final int childHeight = changedView.getHeight();                float offset = (getHeight()- changedView.getTop()) * 1.0f / childHeight;                changedView.setVisibility(offset == 0 ? View.INVISIBLE : View.VISIBLE);                invalidate();            }        });        //设置edge_left track        mHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_BOTTOM);        //设置minVelocity        mHelper.setMinVelocity(minVel);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)    {        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        setMeasuredDimension(widthSize, heightSize);        View leftMenuView = getChildAt(1);        MarginLayoutParams lp = (MarginLayoutParams)                leftMenuView.getLayoutParams();        final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec, lp.leftMargin + lp.rightMargin, lp.width);        final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec, lp.topMargin + lp.bottomMargin, lp.height);        leftMenuView.measure(drawerWidthSpec, drawerHeightSpec);        View contentView = getChildAt(0);        lp = (MarginLayoutParams) contentView.getLayoutParams();        final int contentWidthSpec = MeasureSpec.makeMeasureSpec(                widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);        final int contentHeightSpec = MeasureSpec.makeMeasureSpec(                heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);        contentView.measure(contentWidthSpec, contentHeightSpec);        bottomMenuView = leftMenuView;        mContentView = contentView;    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b)    {        View menuView = bottomMenuView;        View contentView = mContentView;        MarginLayoutParams lp = (MarginLayoutParams) contentView.getLayoutParams();        contentView.layout(lp.leftMargin, lp.topMargin,                lp.leftMargin + contentView.getMeasuredWidth(),                lp.topMargin + contentView.getMeasuredHeight());        lp = (MarginLayoutParams) menuView.getLayoutParams();        menuView.layout(lp.leftMargin, contentView.getMeasuredHeight(), contentView.getMeasuredWidth(),  contentView.getMeasuredHeight() + menuView.getMeasuredHeight());    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev)    {        boolean shouldInterceptTouchEvent = mHelper.shouldInterceptTouchEvent(ev);        return shouldInterceptTouchEvent;    }    @Override    public boolean onTouchEvent(MotionEvent event)    {        mHelper.processTouchEvent(event);        return true;    }    @Override    public void computeScroll()    {        if (mHelper.continueSettling(true))        {            invalidate();        }    }    @Override    protected LayoutParams generateDefaultLayoutParams()    {        return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);    }    public LayoutParams generateLayoutParams(AttributeSet attrs)    {        return new MarginLayoutParams(getContext(), attrs);    }    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p)    {        return new MarginLayoutParams(p);    }}

简单说下心得,自定义GroupView不必多说重点是ViewDragHelper.Callback()中的几个我个人觉得重要的回调方法。容我一一说来

  • clampViewPositionVertical(View child, int top, int dy)
    简单来说就是传进来的这个view的滑动范围,
 //底部菜单滑动只能是自己的高度  if(child==bottomMenuView)   {     final int topBound=getHeight()-child.getHeight();     final int bottomBound=getHeight();  final int newtop=Math.min(Math.max(top,topBound),bottomBound);     return newtop;    }    如果您不懂怎么使用,看上面这个方法,两个Bound就是滑动区域,您自己合计。套用下面的方式就成。
  • onEdgeDragStarted(int edgeFlags, int pointerId)
    介个方法也就是当触摸边界的时候会回调,在该方法中直接
   mHelper.captureChildView(bottomMenuView, pointerId);   //把屏幕看不到View交给捕获方法。 

另外重点这个方法需要
mHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_BOTTOM);设置触摸那个边界。

  • onViewReleased(View releasedChild, float xvel, float yvel)
    个人认为这个方法真的是好方便,以后获取view的滑动速度,我地天费死劲了
VelocityTracker vTracker vTracker = VelocityTracker.obtain();   vTracker.addMovement(event);    vTracker.computeCurrentVelocity(1000); 

我天想想都烦。ViewDragHelper直接利用view释放的回调方法把两个方向的速度传了进来。自行去判断是否关闭还是打开,并且把当前位置的View传了进来。
- onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
当View的位置发生改变就会回调这个方法,这里我遇到个很无聊的小问题,也是自己粗心没有意识到,每次在滑动的过程中,我的view都没有跟随出现,后来去看了下鸿翔老师的博客在发现这个方法,每次都得去重绘乖乖,这个方法做些动画什么的很有用。

好了妥了,记录下,也更新下博客。直接在我的自定义GroupView里面放View就可以啦。无聊的可以试试,只是少了写回调方法。自行解决。

0 0
原创粉丝点击