Android 自定义View动画篇之进阶
来源:互联网 发布:猎户座飞船 火星 知乎 编辑:程序博客网 时间:2024/05/17 23:29
Android 自定义View动画篇之进阶
- Android 自定义View动画篇之进阶
- Interpolator
- TypeEvaluator
上一篇学习了一下属性动画的基础使用方法,还遗留了几个要点,就是TypeEvaluator< T >
、 TimeInterpolator
以及ofObject
的使用。在这一篇就会涉及到。
1.Interpolator
看我们之前属性动画的基础知识里面,包括了起始终点、重复次数、时长等,只能制造简单的动画。只有通过变动动画的执行速率,才能产生丰富有趣的动画来。所以,这里Interpolator就是起到这样一个作用的。
Interpolator一般称为差值器。而TimeInterpolator是属性动画独有的接口,其下有很多的实现类,都是Android给我们封装好了的,可以直接拿来用。比如说,匀速LinearInterpolator
, 加速AccelerateInterpolator
,先加速后减速AccelerateDecelerateInterpolator
等等,而当我们没有设置时的默认差值器就是AccelerateDecelerateInterpolator
。
通过 查看TimeInterpolator接口源码,我们就知道了只需要先实现TimeInterpolator,实现getInterpolation方法即可。getInterpolation中的参数input就是从0到1匀速变化。那么我们就来自定义Interpolator吧。
我们也写个加速运动吧。灵机一动,自由落体就是加速运动啊,公式相信大家都知道吧,那就开始吧。
public class FailingInterpolator implements TimeInterpolator { @Override public float getInterpolation(float input) { return input * input; }}
估计大家以为会很复杂,结果呵呵,就一句话。但是这里没有用加速度10m/s²,为什么呢?如果想真的是自由落体,那么距离就和时间有关系了。限定了距离,时间就固定,限定了时间,距离也要重新计算,除非不想限定运行的距离。那这里加速度是多少呢,比较简单,自己看看。
给个自定义View的代码,以防有的人看不太懂。
public class FailingView extends View { private static final float radius = 100; private Bitmap mBitmap; private int mWidth, mHeight; private Point mPoint; public FailingView(Context context) { this(context, null); } public FailingView(Context context, AttributeSet attrs) { super(context, attrs); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; mBitmap = BitmapFactory.decodeResource(this.getResources(), R.mipmap.mana, options); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(mPoint == null) { mPoint = new Point(mWidth/2, 0); startAnimator(); drawBitmap(canvas); }else { drawBitmap(canvas); } } private void drawBitmap(Canvas canvas) { canvas.drawBitmap(mBitmap, mPoint.getX() - mBitmap.getWidth()/2, mPoint.getY(), null); } private void startAnimator() { ValueAnimator mAnimator = ValueAnimator.ofFloat(0, mHeight); mAnimator.setInterpolator(new FailingInterpolator()); mAnimator.setDuration(2000); mAnimator.start(); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mPoint.setY((Float) animation.getAnimatedValue()); invalidate(); } }); }}
这里都是前面的知识点,只需要通过setInterpolator
设置我们的自定义Interpolater就行了。来看一下结果吧。
2.TypeEvaluator
TypeEvaluator就是设定从初始值变化到结束值的“姿势”,是躺着的过去的,还是跑着过去的。我们可以看一下TypeEvaluator的实现类FloatEvaluator,源码很简单,就是实现TypeEvaluator,然后重写其唯一的方法evaluate。evaluate方法中有三个参数,后面两个看名字就知其含义了,起始值和结束值,而最后一个fraction表示动画的完成度。其实上面自定义Interpolater的返回值就是它了。
刚才说了既然Interpolater的返回值就是fraction,那么就有一种特殊情况了,就是在getInterpolation方法中input不做变换。这样我们就可以做出和上面的例子一样的效果,同样是加速下落。考虑到在画bitmap时,需要限定绘画的位置,通过改变这个点,就能达到重复绘制bitmap,从而产生动画。所以我们需要先新建一个点的bean文件。
public class Point { private float x; private float y; public Point() { } public Point(float x, float y) { this.x = x; this.y = y; } public void setX(float x) { this.x = x; } public float getX() { return x; } public void setY(float y) { this.y = y; } public float getY() { return y; }}
接下来才是写我们的自定义TypeEvaluator了。
public class FailingEvaluator implements TypeEvaluator { @Override public Object evaluate(float fraction, Object startValue, Object endValue) { Point mPoint; Point startPoint = (Point) startValue; Point endPoint = (Point) endValue; mPoint = new Point(0, startPoint.getY() + endPoint.getY() * fraction * fraction); return mPoint; }}
详细的代码就不贴了,相信应该都会写了,来看下效果,应该和上面的一样的。忘记说了ofObject的用法,这里就用到了ValueAnimator的ofObject方法,而ObjectAnimator的ofObject方法的用法差不多,就不单独给示例了。
ValueAnimator mAnimator = ValueAnimator.ofObject(new FailingEvaluator(), new Point(0, 0), new Point(0, mHeight));
了解了原理之后,就来个稍微难一点的例子吧。既然是从初始值到结束值的一个过程,那么能否规定它运动的轨迹呢?就考虑到了使用前面绘图篇的相关知识了path等。这里给出的例子,同样是控制绘图点,达到圆形运动的效果。来看下代码。
public class PathEvaluator implements TypeEvaluator { private static final float radius = 100; private float[] pos; private Point result; @Override public Object evaluate(float fraction, Object startValue, Object endValue) { Point startPoint = (Point) startValue; Point endPoint = (Point) endValue; Path mPath = new Path(); pos = new float[2]; result = new Point(0, 0); if(startPoint.getX() == endPoint.getX() && startPoint.getY() == endPoint.getY()) { RectF rectF = new RectF(startPoint.getX() - 2 * radius, startPoint.getY() - radius, startPoint.getX(), startPoint.getY() + radius); mPath.addArc(rectF, 0, 359.9f); PathMeasure pathMeasure = new PathMeasure(mPath, false); pathMeasure.getPosTan(pathMeasure.getLength() * fraction, pos, null); result.setX(pos[0]); result.setY(pos[1]); } return result; }}
如果学习了前面的绘图篇,这个显然就不难了。来看下效果。
中间是卡了下,不要介意,懒的录了。。。
这些天都没写博客,感觉有点松懈了。就当休息了吧,这段时间要加油了。上一篇说要写个综合的例子,其实是我想了好久都没写成功,然后强迫症犯了,一直没更新。额,下一篇应该会比较快,先立个flag吧。
PS:本人水平实在有限,如有错误之处,还望不吝赐教!
参考:
Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
- Android 自定义View动画篇之进阶
- Android 自定义View绘图篇之进阶
- 笔记—自定义View之属性动画进阶篇
- Android 自定义View动画效果进阶
- Android 自定义View动画篇之基础
- Android自定义View之popupwindow进阶封装:高仿ios “item动画弹出”效果的popupwindow。
- [android进阶]自定义View之TopBar
- Android开发进阶之自定义view
- Android进阶之自定义view(一)
- Android进阶之自定义view(二)
- Android进阶之自定义view(三)
- Android进阶之自定义view(四)
- 【Android进阶之自定义View(一)】
- 【Android进阶之自定义View(二)】
- 【Android进阶之自定义View(三)】
- Android 自定义View进阶
- Android 自定义View进阶
- Android自定义view之属性动画初见
- Ubuntu16.04安装32位支持库
- P2P中的NAT穿越方案简介
- 两种常见的OpenCV Error
- 带cuda的opencv2.4.9 in ubuntu 14.04
- 亲测SQLServer的最大连接数
- Android 自定义View动画篇之进阶
- S5PV210 WM8960 ASOC 移植
- 文件共享神器:NitroShare
- JVM中的内存分配策略
- 文件、目录的调用顺序
- 【leetcode】110.Balanced Binary Tree
- web前端优秀框架
- ubunto16.04 安装virtualbox5.1.2
- 多元时间序列分析