ViewDragHelper制作底部弹出菜单
来源:互联网 发布:外星人源码站 编辑:程序博客网 时间:2024/04/28 18:17
周日难得清闲,遂在网上闲逛。突然发现 Android Support Library 23.2里面多了一个Bottom Sheets—-WOW。感觉蛮不错的,越来越方便了。难耐心中有些不甘,所以正好利用最近学到的ViewDragHelper来仿制一个底部弹出的菜单。
1.首先感谢谷歌大法中的Drawerlayout
2.然后感谢鸿翔老师的精品博客 http://blog.csdn.net/hongxiang_ecjtu(目测刚结婚了)
话不多说先上图
然后上代码
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就可以啦。无聊的可以试试,只是少了写回调方法。自行解决。
- ViewDragHelper制作底部弹出菜单
- 实现底部弹出菜单
- ExpandableButtonMenu |底部弹出菜单
- android底部弹出菜单
- android 底部弹出菜单
- RadioButton 底部菜单制作
- android 仿微信底部弹出菜单
- ios 底部弹出框菜单
- Dialog 实现底部弹出菜单
- Android 实现底部弹出菜单
- popupwindow仿侧滑菜单底部弹出
- Dreamweaver制作弹出菜单
- 制作右键弹出菜单
- android 底部弹出菜单(带透明背景)
- 同时弹出顶部和底部的菜单
- android开发 - 自定义 弹出 底部菜单
- Android DialogFragment实现底部弹出菜单效果
- android 底部弹出菜单(带透明背景)
- 二维树状数组模板(1892)
- 使用Gitlab一键安装包后的日常备份恢复与迁移
- EditText
- 【PPT】跨境电商的N个知识点普及
- hdoj 2019 数列有序!(水)
- ViewDragHelper制作底部弹出菜单
- hdu 5612 Baby Ming and Matrix games
- 网易互联网产品策划专员笔试题
- Java Copy On Write
- 日常总结
- JS的第二周
- 数据库范式概念解析(第一范式,第二范式,第三范式)
- Android:layout_weight属性的两种用法
- 关于PHP中的引用以及clone详解