Android中View的弹性滑动——Android开发艺术探索笔记
2016-02-24 17:05
501 查看
欢迎转载,转载请注明出处/article/3686061.html
本文中的“滑动”是指View内容的滑动而非View本身位置的改变。
![](http://img.blog.csdn.net/20160224170250458)
View在平移过程中,top和left表示的是原始左上角的位置信息,其值不会改变,发生改变的是x、y、translationX、translationY这四个参数。
x是View左上角的坐标,translation是view移动后相对于父容器的偏移量,所以有x = left + translationX。y的原理相同。
getX/getY返回的是相对于当前View左上角的x和y坐标,而getRawX/getRawY返回的是相对于手机屏幕左上角的x和y坐标。
上面是使用Scroller实现弹性滑动的一个典型方法。
实现原理为:Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合使用才能共同完成这个功能。在startScroll()方法下调用了invalidate(),这使得View重绘,View重绘的时候会在draw方法中调用computeScroll(),在此方法中调用scrollTo滑向指定位置。之后再通过postInvalidate()进行二次重绘,如此重复直到滑动结束。
下面是computeScrollOffset()这个函数的源码。从中可以看出判断滑动是否结束是以timePassed为标准的。
上述代码中,动画本质上没有作用于任何对象上,只是在1000ms内完成了整个动画过程。这个方法scrollTo(startX + (int) (deltaX * fraction), 0)使得动画每次更新时view都滑动一点。
在Handler的handleMessage中调用View的scrollTo方法滑动一些距离,紧接着再向Handler发送一个Delay的消息再次滑动。关键方法mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME)。
欢迎转载,转载请注明出处/article/3686061.html
介绍
弹性滑动也就是渐进式滑动,实现弹性滑动的方法有很多,但是他们都有一个共同的思想:将一次大的滑动分成若干次小的滑动并在一段时间内完成。本文主要介绍三种弹性滑动方式,Scroller、动画和Handler。本文中的“滑动”是指View内容的滑动而非View本身位置的改变。
示例
点击屏幕任意地方,手指与屏幕接触时,触发ACTION_DOWN屏幕中的文字会向上滑动400px,手指离开屏幕时触发ACTION_UP文字下滑400px。基础知识补充
View的宽高和坐标关系:width = right - left,height = top - bottom。View在平移过程中,top和left表示的是原始左上角的位置信息,其值不会改变,发生改变的是x、y、translationX、translationY这四个参数。
x是View左上角的坐标,translation是view移动后相对于父容器的偏移量,所以有x = left + translationX。y的原理相同。
getX/getY返回的是相对于当前View左上角的x和y坐标,而getRawX/getRawY返回的是相对于手机屏幕左上角的x和y坐标。
使用Scroller
[code]private void smoothScrollTo(int destX, int destY) { int scrollX = getScrollX(); int detlaX = destX - scrollX; int scrollY = getScrollY(); int detlaY = destY - scrollY; Log.d(TAG, "smoothScrollTo:scrollY, detlaY= " + scrollY+" " + detlaY); mScroller.startScroll(scrollX, scrollY, detlaX, detlaY, 1000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } }
上面是使用Scroller实现弹性滑动的一个典型方法。
实现原理为:Scroller本身无法让View弹性滑动,它需要和View的computeScroll方法配合使用才能共同完成这个功能。在startScroll()方法下调用了invalidate(),这使得View重绘,View重绘的时候会在draw方法中调用computeScroll(),在此方法中调用scrollTo滑向指定位置。之后再通过postInvalidate()进行二次重绘,如此重复直到滑动结束。
下面是computeScrollOffset()这个函数的源码。从中可以看出判断滑动是否结束是以timePassed为标准的。
[code]/** * Call this when you want to know the new location. If it returns true, * the animation is not yet finished. */ public boolean computeScrollOffset() { if (mFinished) { return false; } int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); if (timePassed < mDuration) { switch (mMode) { case SCROLL_MODE: final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal); mCurrX = mStartX + Math.round(x * mDeltaX); mCurrY = mStartY + Math.round(x * mDeltaY); break; case FLING_MODE: ... ... break; } } else { mCurrX = mFinalX; mCurrY = mFinalY; mFinished = true; } return true; }
使用动画
[code] private static final int FRAME_COUNT = 30; final int startX = 0; final int deltaX = 100; ValueAnimator animator = ValueAnimator.ofInt(0,1).setDuration(1000); animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { float fraction = animator.getAnimatedFraction(); mButton1.scrollTo(startX + (int) (deltaX * fraction), 0); } }); animator.start();
上述代码中,动画本质上没有作用于任何对象上,只是在1000ms内完成了整个动画过程。这个方法scrollTo(startX + (int) (deltaX * fraction), 0)使得动画每次更新时view都滑动一点。
使用Handler
[code] private static final int MESSAGE_SCROLL_TO = 1; private static final int DELAYED_TIME = 33; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_SCROLL_TO: { mCount++; if (mCount <= FRAME_COUNT) { float fraction = mCount / (float) FRAME_COUNT; int scrollX = (int) (fraction * 100); mButton1.scrollTo(scrollX, 0); mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME); } break; } default: break; } }; };
在Handler的handleMessage中调用View的scrollTo方法滑动一些距离,紧接着再向Handler发送一个Delay的消息再次滑动。关键方法mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME)。
示例动画效果的源码
示例中的动画效果是在一个TextView进行的,滑动的是TextView中的文字。源码如下。[code] /** * Created by Spark on 2/22/2016 21:12. */ public class ElasticText extends TextView { private static final String TAG = "ElasticText"; private Scroller mScroller; private VelocityTracker mVelocityTracker; public ElasticText(Context context) { super(context); init(); } public ElasticText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ElasticText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mScroller = new Scroller(getContext()); mVelocityTracker = VelocityTracker.obtain(); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { Log.d(TAG, "onTouchEvent: ActionDown"); mScroller.startScroll(getScrollX(), getScrollY(), 0, 400, 600); invalidate(); break; } case MotionEvent.ACTION_MOVE: { break; } case MotionEvent.ACTION_UP: { Log.d(TAG, "onTouchEvent: ACTION_UP"); mScroller.startScroll(getScrollX(), getScrollY(), 0, -400, 600); invalidate(); break; } default: break; } return true; } private void smoothScrollTo(int destX, int destY) { int scrollX = getScrollX(); int detlaX = destX - scrollX; int scrollY = getScrollY(); int detlaY = destY - scrollY; mScroller.startScroll(scrollX, scrollY, detlaX, detlaY, 1000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } }
欢迎转载,转载请注明出处/article/3686061.html
相关文章推荐
- Android利用系统广播---监听应用程序安装和卸载
- Android ListView 全面优化
- Android java.lang.reflect.InvocationTargetException 错误
- Android:CoolWeather天气查看器
- android绘图Paint.setAntiAlias()和Paint.setDither()方法的作用
- [Android4.4]Audio添加控制MIC左右声道接口
- Android学习笔记day5
- 给 Android 开发者的 RxJava 详解
- You must specifiy a layout in the include tag: <include layout="@layout/layoutID" />
- Android6.0权限问题导致下载没效果
- 快速Android开发系列通信篇之EventBus
- Android-Tab单选控件
- Android Context完全解析
- Android-节日短信送祝福(知识点总结)
- android studio之配置NDK开发环境
- 解决android2.1中Youku每次都要选择默认播放器的问题
- Android插件化开发 第三篇 [加载插件资源]
- android夯实总结(设计、细节及思想)
- Android--activity切换时的动画
- android个人笔记:圆角,线,框,渐变