Android实现滑动的七种方法
1.layout方法
每次移动后,调用layout()方法对自己重新布局从而达到移动的效果
- @Override
 - public boolean onTouchEvent(MotionEvent event) {
 - int x = (int) event.getX();
 - int y = (int) event.getY();
 - switch (event.getAction()) {
 - case MotionEvent.ACTION_DOWN:
 - // 记录触摸点坐标
 - lastX = x;
 - lastY = y;
 - break;
 - case MotionEvent.ACTION_MOVE:
 - // 计算偏移量
 - int offsetX = x - lastX;
 - int offsetY = y - lastY;
 - // 在当前left、top、right、bottom的基础上加上偏移量
 - layout(getLeft() + offsetX,
 - getTop() + offsetY,
 - getRight() + offsetX,
 - getBottom() + offsetY);
 - break;
 - }
 - return true;
 - }
 
2.offsetLeftAndRight()和offsetTopAndBottom()
系统提供的一个对左右、上下移动的API封装,效果和使用layout()一样
- offsetLeftAndRight(offsetX);
 - offsetTopAndBottom(offsetY);
 
3.LayoutParams
LayoutParams里保存了View的布局参数,通常通过改变LayoutParams来改变一个View的位置都是通过改变这个View的Margin属性。
- case MotionEvent.ACTION_MOVE:
 - // 计算偏移量
 - int offsetX = x - lastX;
 - int offsetY = y - lastY;
 - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
 - layoutParams.leftMargin = getLeft() + offsetX;
 - layoutParams.topMargin = getTop() + offsetY;
 - setLayoutParams(layoutParams);
 - break;
 
4.ScrollTo与ScrollBy
这两个方法移动的是View的内容,我们应该在要移动的View所在的ViewGroup中来使用这两个方法。
这两个方法的区别是scrollTo(x, y)表示移动到一个具体的坐标点(x, y),而scrollBy(dx, dy)表示移动的增量为dx、dy。
同时要想实现跟随手指一动而华东的效果,需要将偏移量设置为负数
- @Override
 - public boolean onTouchEvent(MotionEvent event) {
 - int x = (int) event.getX();
 - int y = (int) event.getY();
 - switch (event.getAction()) {
 - case MotionEvent.ACTION_DOWN:
 - lastX = (int) event.getX();
 - lastY = (int) event.getY();
 - break;
 - case MotionEvent.ACTION_MOVE:
 - int offsetX = x - lastX;
 - int offsetY = y - lastY;
 - ((View) getParent()).scrollBy(-offsetX, -offsetY);
 - break;
 - }
 - return true;
 - }
 
5.Scroller类
通过Scroller类可以实现平滑移动的效果,而不再是瞬间完成的动作。
使用Scroller类需要三个步骤:
- 初始化Scroller
 - 重写computeScroll()方法。用来判断是否完成了整个滑动
 - 开始滑动。startScroll(int startX, int startY, int dx, int dy, int duration)和startScroll(int startX, int startY, int dx, int dy)方法,区别是其中一个具有指定时长
 
- private void ininView(Context context) {
 - // 初始化Scroller
 - mScroller = new Scroller(context);
 - }
 - @Override
 - public void computeScroll() {
 - super.computeScroll();
 - // 判断Scroller是否执行完毕
 - if (mScroller.computeScrollOffset()) {
 - ((View) getParent()).scrollTo(
 - mScroller.getCurrX(),
 - mScroller.getCurrY());
 - // 通过重绘来不断调用computeScroll
 - invalidate();
 - }
 - }
 - @Override
 - public boolean onTouchEvent(MotionEvent event) {
 - int x = (int) event.getX();
 - int y = (int) event.getY();
 - switch (event.getAction()) {
 - case MotionEvent.ACTION_DOWN:
 - lastX = (int) event.getX();
 - lastY = (int) event.getY();
 - 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;
 - }
 - return true;
 - }
 
6.属性动画
详情见属性动画的介绍
7.ViewDragHelper
使用步骤:
- 初始化ViewDragHelper
 
- mViewDragHelper = ViewDragHelper.create(this, callback);
 
- 拦截事件
 
- @Override
 - public boolean onInterceptTouchEvent(MotionEvent ev) {
 - return mViewDragHelper.shouldInterceptTouchEvent(ev);
 - }
 - @Override
 - public boolean onTouchEvent(MotionEvent event) {
 - //将触摸事件传递给ViewDragHelper,此操作必不可少
 - mViewDragHelper.processTouchEvent(event);
 - return true;
 - }
 
- 处理computeScroll()
 
- @Override
 - public void computeScroll() {
 - if (mViewDragHelper.continueSettling(true)) {
 - ViewCompat.postInvalidateOnAnimation(this);
 - }
 - }
 
- 处理回调CallBack
 
- private ViewDragHelper.Callback callback =
 - new ViewDragHelper.Callback() {
 - // 何时开始检测触摸事件
 - @Override
 - public boolean tryCaptureView(View child, int pointerId) {
 - //如果当前触摸的child是mMainView时开始检测
 - return mMainView == child;
 - }
 - // 触摸到View后回调
 - @Override
 - public void onViewCaptured(View capturedChild,
 - int activePointerId) {
 - super.onViewCaptured(capturedChild, activePointerId);
 - }
 - // 当拖拽状态改变,比如idle,dragging
 - @Override
 - public void onViewDragStateChanged(int state) {
 - super.onViewDragStateChanged(state);
 - }
 - // 当位置改变的时候调用,常用与滑动时更改scale等
 - @Override
 - public void onViewPositionChanged(View changedView,
 - int left, int top, int dx, int dy) {
 - super.onViewPositionChanged(changedView, left, top, dx, dy);
 - }
 - // 处理垂直滑动
 - @Override
 - public int clampViewPositionVertical(View child, int top, int dy) {
 - return 0;
 - }
 - // 处理水平滑动
 - @Override
 - public int clampViewPositionHorizontal(View child, int left, int dx) {
 - return left;
 - }
 - // 拖动结束后调用
 - @Override
 - public void onViewReleased(View releasedChild, float xvel, float yvel) {
 - super.onViewReleased(releasedChild, xvel, yvel);
 - //手指抬起后缓慢移动到指定位置
 - if (mMainView.getLeft() < 500) {
 - //关闭菜单
 - //相当于Scroller的startScroll方法
 - mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
 - ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
 - } else {
 - //打开菜单
 - mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
 - ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
 - }
 - }
 - };
 
详细代码可见Android群英传
-------------------------------Android群英传第五章
                    
                
                
            
        
浙公网安备 33010602011771号