可移动自定义viewgroup--viewdraghelp心得
来源:互联网 发布:网络直播的利弊 编辑:程序博客网 时间:2024/05/18 00:52
最近项目需要一个可移动的viewgroup控件,这方面还是比较弱的(因为之前都没怎么做这个,而且网上的自定义控件文章很多,看了好久还是没有自信。我想还是没有彻底理解把,唉)在此感谢zhy大神,他的文章总是帮助好多。感谢大神,感谢开源精神。
SlidingPaneLayout和DrawerLayout这两个google的控件不知道大家有没有用过,据说都用到了viewdraghelper。因为我没有看过源码,只是听说。但是这已经说明了它的强大,不是吗?此处有‘赢笑’图片。为什么叫helper类呢,因为android手势处理还是比较复杂的,所以这个帮助类是帮助我们的快速实现的。
- 创建实例(通过静态工厂方法创建的)
- 触摸相关的方法的调用
ViewDragHelper.Callback实例的编写(大部分方法都在callback里面)
开始自定义控件首先当然是继承RelativeLayout(布局viewgroup)
- ViewDragHelper的初始化
- ViewDragHelper.Callback
- 触摸相关的方法的调用
代码
初始化viewdraghelper
/** * 1.0f传入的值越大,越来越难拉 */ mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
重写callback的方法
此方法决定哪个view可以滑动
/** * tryCaptureView如果返回ture则表示可以捕获该view,你可以根据传入的第一个view参数决定哪些可以捕获 * @param child * @param pointerId * @return */ @Override public boolean tryCaptureView(View child, int pointerId) { return child == mAutoBackView;// return true; }
设定左右上下滑动的范围
/** * 设定左右上下滑动的范围 * @param child * @param left * @param dx * @return */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return (getWidth() - mAutoBackView.getWidth())/2; } @Override public int clampViewPositionVertical(View child, int top, int dy) { int topBound = getPaddingTop(); int bottomBound = getHeight() - mBottomView.getHeight() - topBound - mAutoBackView.getHeight(); int newTop = Math.min(Math.max(top,topBound),bottomBound); return newTop; }
手指释放时调用的方法
/** * 手指释放的时候回调 * @param releasedChild * @param xvel * @param yvel */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { if (releasedChild == mAutoBackView) {// mAutoBackView.getScrollY()// Log.d("yzj------",""+mAutoBackView.getScrollY());// Log.d("yzj------","mAutoBackOriginPos.x:"+mAutoBackOriginPos.x+"mAutoBackOriginPos.y:"+mAutoBackOriginPos.y); mDragger.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y); invalidate(); flag = false; } super.onViewReleased(releasedChild, xvel, yvel); }
当在边缘滑动的时候调用
/** * 在边缘滑动的时候调用 * @param edgeFlags * @param pointerId */ @Override public void onEdgeTouched(int edgeFlags, int pointerId) { super.onEdgeTouched(edgeFlags, pointerId); }
view位置改变时调用
/** * view位置改变时调用 * @param changedView * @param left * @param top * @param dx * @param dy */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); if(top == getHeight() - mBottomView.getHeight() - getPaddingTop() - mAutoBackView.getHeight() && (flag == false)){ Log.d("yzj------","move to the most"); flag = true; } }
接下来是触摸相关的方法的调用
@Override public boolean onInterceptTouchEvent(MotionEvent event) { return mDragger.shouldInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { mDragger.processTouchEvent(event); return true; }
layout完成时调用
/** * 得到初始化位置 * * @param changed * @param l * @param t * @param r * @param b */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mAutoBackOriginPos.x = mAutoBackView.getLeft(); mAutoBackOriginPos.y = mAutoBackView.getTop(); }
完成inflate时的调用
@Override protected void onFinishInflate() { super.onFinishInflate(); mAutoBackView = getChildAt(1); mBottomView = getChildAt(2); }
通过以上几个方法的调用我相信能帮你实现很多的东西。最后放上全部的代码
public class VDRLayout extends RelativeLayout { //helper类 private ViewDragHelper mDragger; //回弹view private View mAutoBackView; //记录初始位置 private Point mAutoBackOriginPos = new Point(); private View mBottomView; private boolean flag; public VDRLayout(Context context, AttributeSet attrs) { this(context, null, 0); } public VDRLayout(Context context) { this(context, null); } public VDRLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /** * 1.0f传入的值越大,越来越难拉 */ mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() { /** * tryCaptureView如果返回ture则表示可以捕获该view,你可以根据传入的第一个view参数决定哪些可以捕获 * @param child * @param pointerId * @return */ @Override public boolean tryCaptureView(View child, int pointerId) { return child == mAutoBackView;// return true; } /** * 设定左右上下滑动的范围 * @param child * @param left * @param dx * @return */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return (getWidth() - mAutoBackView.getWidth())/2; } @Override public int clampViewPositionVertical(View child, int top, int dy) { int topBound = getPaddingTop(); int bottomBound = getHeight() - mBottomView.getHeight() - topBound - mAutoBackView.getHeight(); int newTop = Math.min(Math.max(top,topBound),bottomBound); return newTop; } /** * 手指释放的时候回调 * @param releasedChild * @param xvel * @param yvel */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { if (releasedChild == mAutoBackView) {// mAutoBackView.getScrollY()// Log.d("yzj------",""+mAutoBackView.getScrollY());// Log.d("yzj------","mAutoBackOriginPos.x:"+mAutoBackOriginPos.x+"mAutoBackOriginPos.y:"+mAutoBackOriginPos.y); mDragger.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y); invalidate(); flag = false; } super.onViewReleased(releasedChild, xvel, yvel); } /** * 在边缘滑动的时候调用 * @param edgeFlags * @param pointerId */ @Override public void onEdgeTouched(int edgeFlags, int pointerId) { super.onEdgeTouched(edgeFlags, pointerId); } /** * view位置改变时调用 * @param changedView * @param left * @param top * @param dx * @param dy */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); if(top == getHeight() - mBottomView.getHeight() - getPaddingTop() - mAutoBackView.getHeight() && (flag == false)){ Log.d("yzj------","move to the most"); flag = true; } } }); //允许哪个边缘可以调用 mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_BOTTOM); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { //决定我们是否应该拦截当前的事件 return mDragger.shouldInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { //处理事件 mDragger.processTouchEvent(event); return true; } @Override public void computeScroll() { if (mDragger.continueSettling(true)) { invalidate(); } } /** * 得到初始化位置 * * @param changed * @param l * @param t * @param r * @param b */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mAutoBackOriginPos.x = mAutoBackView.getLeft(); mAutoBackOriginPos.y = mAutoBackView.getTop(); } @Override protected void onFinishInflate() { super.onFinishInflate(); mAutoBackView = getChildAt(1); mBottomView = getChildAt(2); }}
0 0
- 可移动自定义viewgroup--viewdraghelp心得
- 【移动开发】如何自定义ViewGroup
- android 利用ViewDragHelper实现childView可随手指移动的自定义ViewGroup
- 自定义ViewGroup以及View的一些心得。
- 自定义ViewGroup,子View可对换位置
- 自定义可移动view
- 自定义View绘制心得(自定义view和自定义viewGroup)
- 自定义ViewGroup[跟随手指移动的view]
- 关于两个可移动ViewGroup触摸事件冲突处理
- c#自定义窗口可移动
- 可滑动弹出菜单的自定义Layout,基于ViewGroup
- ScrollerLayout——可横向滚动的自定义viewgroup
- 自定义view,继承ViewGroup实现可换行的布局容器
- 自定义Viewgroup(2)--可滚动的横向布局
- 自定义viewgroup(5)--可滚动布局,GestureDetector手势监听
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 无线网卡工作模式笔记
- Java使用poi操作cexel
- 总结javaweb 目录结构
- PAT 1002. 写出这个数 (20)
- 程序员不爱读书,但这很不明智
- 可移动自定义viewgroup--viewdraghelp心得
- CSS 定位(Positioning)
- PAT 1003. 我要通过!(20)
- Zygote,SystemServer启动分析
- [leetcode] 344. Reverse String
- C++二级指针的深入了解
- PAT 1004. 成绩排名 (20)
- 设计模式:组合模式(Composite)
- 别为了学编程而学编程