android 群英传笔记----Android scroll
来源:互联网 发布:数据流量设置dns 编辑:程序博客网 时间:2024/05/29 08:55
现在流行的app中都存在大量的滑动操作,但是一直没有去研究过,实在是不应该,正好这本书有讲解,就参考本书学习一下
- 滑动产生的原因
- 如何实现、处理滑动效果
1 . 滑动产生的原因
滑动一个View,本质上来说就是移动一个View。改变其当前所处位置,它的原理与动画效果非常相似,都是通过不断改变View的坐标来实现这一效果。所以,要实现View的滑动,就必须监听用户的触摸事件,从而实现View跟随用户触摸的滑动而滑动。
1.1 坐标系
如下图所示:
1.2 常见的获取坐标方法
2 .实现滑动的7中方法
要实现的效果:让自定义View随着手指在屏幕上的滑动而滑动
- layout()方法
public class DragViewLayout extends View { private int lastX; private int lastY; public DragViewLayout(Context context) { super(context); } public DragViewLayout(Context context, AttributeSet attrs) { super(context, attrs); } public DragViewLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action){ case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y-lastY; layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY); break; case MotionEvent.ACTION_UP: break; default: break; } return true; }}
- offsetLeftAndrRight()与offsetTopAndBottom()
public class DragViewOffset extends View { private int lastX; private int lastY; public DragViewOffset(Context context) { super(context); } public DragViewOffset(Context context, AttributeSet attrs) { super(context, attrs); } public DragViewOffset(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action){ case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y-lastY; offsetLeftAndRight(offsetX); offsetTopAndBottom(offsetY); break; case MotionEvent.ACTION_UP: break; default: break; } return true; }}
- LayoutParams
public class DragViewMargin extends View { private int lastX; private int lastY; private ViewGroup.MarginLayoutParams params; public DragViewMargin(Context context) { super(context); } public DragViewMargin(Context context, AttributeSet attrs) { super(context, attrs); } public DragViewMargin(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action){ case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y-lastY; params = (ViewGroup.MarginLayoutParams) getLayoutParams(); params.leftMargin = getLeft()+offsetX; params.topMargin = getTop()+offsetY; setLayoutParams(params); break; case MotionEvent.ACTION_UP: break; default: break; } return true; }}
- scrollTo 与scrollby,注意参考系的不同
/*** 如果是View使用Scrollby,移动的是view的内容,TextView,content是他的文本,ImageView,content是他的drawable* 如果是ViewGroup,移动的是所有子View*/public class DragViewScrollBy extends View { private int lastX; private int lastY; private ViewGroup.MarginLayoutParams params; public DragViewScrollBy(Context context) { super(context); } public DragViewScrollBy(Context context, AttributeSet attrs) { super(context, attrs); } public DragViewScrollBy(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y - lastY; //此处,是用-offset ((ViewGroup) getParent()).scrollBy(-offsetX, -offsetY); break; case MotionEvent.ACTION_UP: break; default: break; } return true; }}
- Scroller,实现平滑移动效果
/** * Created by acer on 2015/11/5. * 松开手指,回到原位置 * */public class DragViewScroller extends View { private int lastX; private int lastY; private Scroller mscroller; public DragViewScroller(Context context) { super(context); init(context); } public DragViewScroller(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public DragViewScroller(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { mscroller = new Scroller(context); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int x = (int) event.getX(); int y = (int) event.getY(); switch (action) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y - lastY; ((View) getParent()).scrollBy(-offsetX, -offsetY); break; case MotionEvent.ACTION_UP: //手指离开,开始滑动回原位置 View viewGroup = (View) getParent(); mscroller.startScroll(viewGroup.getScrollX(), viewGroup.getScrollY(), -viewGroup.getScrollX(), -viewGroup.getScrollY()); invalidate(); break; default: break; } return true; } /** *computeScroll()方法不会自动调用, *只能通过invalidate()---draw()--computeScroll()来间接调用 * */ @Override public void computeScroll() { if (mscroller.computeScrollOffset()) { ((View) getParent()).scrollTo(mscroller.getCurrX(), mscroller.getCurrY()); //通过重绘,不断调用computeScrol invalidate(); } }}
- ViewGragHelper 强大的滑动控制类,实现各种不同的滑动,拖放需求
public class LearnViewDragHelper extends FrameLayout { private ViewDragHelper mHelper; private View mMenuView; private View mMainView; private int mWidth; public LearnViewDragHelper(Context context) { super(context); init(); } public LearnViewDragHelper(Context context, AttributeSet attrs) { super(context, attrs); init(); } public LearnViewDragHelper(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LearnViewDragHelper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } /** * 加载布局文件完成后调用 */ @Override public void onFinishInflate(){ super.onFinishInflate(); mMenuView = getChildAt(0); mMainView = getChildAt(1); } @Override public void onSizeChanged(int w,int h,int oldw,int oldh){ super.onSizeChanged(w, h, oldw, oldh); mWidth = mMenuView.getMeasuredWidth(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { //将触摸事件传递给ViewDragHelper,此操作必不可少 mHelper.processTouchEvent(event); return true; } private void init() { mHelper = ViewDragHelper.create(this, callback); } /** * 核心回調 **/ private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { /** * 开始检测触摸事件 * @param child * @param pointerId * @return */ @Override public boolean tryCaptureView(View child, int pointerId) { //如果当前触摸的child是mMainView时开始检测 return mMainView==child; } /** * 用户触摸到View后回调 * @param capturedChild * @param activePointerId */ @Override public void onViewCaptured(View capturedChild, int activePointerId) { super.onViewCaptured(capturedChild, activePointerId); } /** * view拖拽状态改变时回调 * @param state */ @Override public void onViewDragStateChanged(int state) { super.onViewDragStateChanged(state); } /** * view position改变时回调,常用于更改scale进行缩放等效果 * @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); } /** * * 通常情况下,只需要返回top 和 left即可,但是当需要更加精确的计算padding等属性的时候,就需要对left进行一些处理,并返回合适大小的值 * */ /** * 水平方向滑动 * @param child * @param left 在水平方向child移动的距离 * @param dx 较前一次的增量 * @return 默认返回0 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return left; } /** * 竖直方向滑动 * @param child * @param top 在竖直方向child移动的距离 * @param dy 较前一次移动的距离 * @return 默认返回0 */ @Override public int clampViewPositionVertical(View child, int top, int dy) { return super.clampViewPositionVertical(child,top,dy); } /** * 拖动结束后调用 * @param releasedChild * @param xvel * @param yvel */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); //手指抬起后,缓慢移动到指定位置 if(mMainView.getLeft()<500){ //关闭菜单,相当于Scroller.startScroll mHelper.smoothSlideViewTo(mMainView,0,0); ViewCompat.postInvalidateOnAnimation(LearnViewDragHelper.this); }else{ //打开菜单 mHelper.smoothSlideViewTo(mMainView,300,0);/***Cause an invalidate to happen on the next animation time *step, typically the next display frame**/ ViewCompat.postInvalidateOnAnimation(LearnViewDragHelper.this); } } }; /** * Move the captured settling view by the appropriate amount for the current time. * If <code>continueSettling</code> returns true, the caller should call it again * on the next frame to continue. * * @param deferCallbacks true if state callbacks should be deferred via posted message. * Set this to true if you are calling this method from * {@link android.view.View#computeScroll()} or similar methods * invoked as part of layout or drawing. * @return true if settle is still in progress */ @Override public void computeScroll() { if (mHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } }}
滑动效果图如下:
DragViewHelper效果图如下:
0 0
- android 群英传笔记----Android scroll
- Scroll 滚动 《Android 群英传》笔记
- Andriod群英传-Android Scroll 分析学习笔记
- Android群英传学习笔记——Android Scroll 分析
- Android群英传笔记——第五章:Android Scroll分析
- Android群英传第五章笔记·Android Scroll分析
- Android群英传笔记——第五章:Android Scroll分析
- Android群英传——Scroll
- Android群英传之Android Scroll分析
- 《Android群英传》读书笔记5.Android Scroll分析
- Android群英传第五章Scroll分析读书笔记
- Android Scroll——Androi群英传
- Scroll滑动分析-《Android群英传》第五章
- 《Android群英传》学习笔记
- Android群英传笔记
- 《Android群英传》学习笔记
- android群英传笔记 surfaceView
- Android群英传笔记集合
- Matlab 出现Undefined function '' for input arguments of type 'double'.解决方案
- 10字典dict
- HOG+SVM 自己制作训练样本+训练分类器
- JAVA获取WEB项目下的WEB-INF目录
- 创建/导入maven项目时 eclipse默认jdk版本配置
- android 群英传笔记----Android scroll
- IOS 七种手势详解(动图+Demo下载)
- C/Cplusplus
- 在Thinkpad中设置电池管理阈值
- MySql enum字段使用问题
- MMORPG游戏设计学习笔记·乱斗西游体验分析&手游设计理解
- 归纳事件的绑定
- 如何用Java调用R(包含在服务器安装的过程)以及用R生成的图片如何用<img>标签访问
- POJ 1503 Integer Inquiry