前言

今天给大家带来的是自定义Evaluator实现弹球效果,我们先给大家来个效果图。

下面我们介绍具体代码流程

1. 自定义Point类

public class Point {

private int radius;

public Point(int radius) {

this.radius = radius;

}

public int getRadius() {

return radius;

}

public void setRadius(int radius) {

this.radius = radius;

}

}

2. 自定义PointEvaluator实现TypeEvaluator接口

class PointEvaluator implements TypeEvaluator{

/**

*@param fraction 动画变化中的浮点参数,0-1

*@param startValue 动画开始时的Point对象

*@param endValue 动画结束时的Point对象

*@return 动画过程中通过计算获取半径并返回一个新的Point对象

*/

@Override

public Point evaluate(float fraction, Point startValue, Point endValue) {

int startRadius = startValue.getRadius();

int endRadius = endValue.getRadius();

int newRadius = (int) (startRadius + fraction * (endRadius - startRadius));

return new Point(newRadius);

}

}

3. 自定义PointView

定义弹球属性attrs

declare-styleable>

获取自定义属性,这里我们只定义了一个弹球颜色属性。

private void initAttrs(Context context, AttributeSet attrs) {

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PointView);

mColor = typedArray.getColor(R.styleable.PointView_point_color, DEFAULT_COLOR);

typedArray.recycle();

}

初始化画笔

private void initPaint() {

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setStyle(Paint.Style.FILL);

mPaint.setColor(mColor);

}

重写onMeasure方法

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

/**

* 测量view的宽高

*/

if (widthMode == MeasureSpec.AT_MOST) {

widthSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_WIDTH, getResources().getDisplayMetrics()) + getPaddingLeft() + getPaddingRight();

}

if (heightMode == MeasureSpec.AT_MOST) {

heightSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_HEIGHT, getResources().getDisplayMetrics()) + getPaddingTop() + getPaddingBottom();

}

/**

* 使用setMeasureDimension方法确定view的最终宽和高

*/

setMeasuredDimension(widthSize, heightSize);

}

在onSizeChanged中获取view的最终宽度和高度

这里minValue是取宽度和高度中的较小值

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

/**

* 在onSizeChanged重载方法中获取view的最终宽度和高度

*/

width = w;

height = h;

/**

* 使用width减去左右的padding

* 使用height减去上下的padding

* 并取两者中的最小值用来确定最大弹球的半径

*/

minValue = Math.min(width - getPaddingLeft() - getPaddingRight(), height - getPaddingTop() - getPaddingBottom());

}

接下来是动画的实现,使用ValueAnimator的ofObject()实现弹球动画

public void startAnimation() {

/**

* 使用ValueAnimator.ofObject()方法并使用自定义的Evaluator实现动画

*/

ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(), new Point(0), new Point(minValue * 2 / 5));

animator.setDuration(2000);

/**

* 设置插值器为BounceInterpolator,其效果为:动画结束的时候弹起

*/

animator.setInterpolator(new BounceInterpolator());

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

/**

* 通过getAnimatedValue获取我们变化中的Point对象

*/

mPoint = (Point) animation.getAnimatedValue();

postInvalidate();

}

});

animator.start();

}

最后是在onDraw函数中绘制弹球

@Override

protected void onDraw(Canvas canvas) {

if (mPoint != null) {

canvas.drawCircle(width / 2, height / 2, mPoint.getRadius(), mPaint);

}

}

4. xml中的引用

android:id="@+id/third_point_view"

android:layout_width="150dp"

android:layout_height="200dp"

android:layout_below="@id/second_point_view"

android:layout_centerHorizontal="true"

android:layout_marginTop="10dp"

android:background="@color/colorPrimary"

app:point_color="#0ff" />

5. 动画实现

在代码中获取PointView的实例然后调用startAnimation()方法实现弹球动画 MainActivity.java

public class MainActivity extends AppCompatActivity {

private PointView pointView;

private PointView secondPointView;

private PointView thirdPointView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

pointView = (PointView) findViewById(R.id.point_view);

secondPointView = (PointView) findViewById(R.id.second_point_view);

thirdPointView = (PointView) findViewById(R.id.third_point_view);

findViewById(R.id.animation_button).setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

pointView.startAnimation();

secondPointView.startAnimation();

thirdPointView.startAnimation();

}

});

}

}

总结

以上就是关于今天自定义Evaluator的全部内容,不懂的童鞋可以留言或者发邮件,另外有需要源码的小伙伴可以去github下载,点击跳转到github源码地址,希望大家多多star!

android弹球动画,Android动画之自定义Evaluator实现弹球效果相关推荐

  1. android 直播评论动画,Android自定义View实现直播点赞特效

    由于开发的需要,需要开发类似直播点赞特效的需求,于是自定义View来实现这种效果 案例图: 1.自定义View import android.animation.Animator; import an ...

  2. android自定义差值器,如何创建自定义插值器以在android中应用翻译动画

    我想创建一个自定义插值来应用平移动画,其中动画应该通过以下函数: public static float easeIn(float t,float b , float c, float d) { re ...

  3. [Android]Fragment自定义动画、动画监听以及兼容性包使用

    Fragment是Android在API 11之后加入的一个组件,对提高Android开发中的布局合理性和布局效率都有很大作用,尤其是在Android平板等大屏幕设备的开发中,Fragment的引入能 ...

  4. android view 渐变动画,Android自定义view渐变圆形动画

    本文实例为大家分享了Android自定义view渐变圆形动画的具体代码,供大家参考,具体内容如下 直接上效果图 自定义属性 attrs.xml文件 创建一个类 ProgressRing继承自 view ...

  5. android 自定义帧动画,Android 自定义方式实现帧动画效果

    前言 首先说下为啥要通过自定义处理的方式去实现Android的帧动画效果,因为通过系统原生支持的xml和java代码这两种方式实现,在播放的图片量很多时,会出现内存溢出,此现象也是在做项目当中有遇到, ...

  6. 球体动画Android,Android自定义View实现简单炫酷的球体进度球实例代码

    前言 最近一直在研究自定义view,正好项目中有一个根据下载进度来实现球体进度的需求,所以自己写了个进度球,代码非常简单.先看下效果: 效果还是非常不错的. 准备知识 要实现上面的效果我们只要掌握两个 ...

  7. android从一点展开动画,Android自定义View——从零开始实现可展开收起的水平菜单栏...

    大家要是看到有错误的地方或者有啥好的建议,欢迎留言评论 前言:最近项目里要实现一个 可展开收起的水平菜单栏控件,刚接到需求时想着用自定义View自己来绘制,发现要实现 圆角.阴影.菜单滑动等效果非常复 ...

  8. android常用窗口动画,android 自定义dialog,窗口动画,

    自定义dialog窗口,根据坐标可随意设置dialog显示位置,实现了窗口弹出动画 Java代码: package com.sunxu.org.IndividualityDialog; import ...

  9. android+清除循环动画,android自定义View之(4)-一键清除动画

    android自定义View之(四)------一键清除动画 1.前言: 自己也是参考别人的一些自定义view例子,学习了一些基本的自定义view的方法.今天,我参考了一些资料,再结合自已的一些理解, ...

最新文章

  1. mysql model first,一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具
  2. Python字典循环与字典排序
  3. T-SQL with as 关键字
  4. 操作es_ES打野皇子操作看呆Uzi:这哥们肯定是深得Lucky真传
  5. 网络通信 route(公司局域网配置)
  6. [CTO札记]Disney也进军数字出版市场了
  7. java 静态变量锁_线程中锁方法和静态变量的锁
  8. vsftpd配置权限问题
  9. 一个被加入下载QQ盗号木马Trojan.PSW.QQPass.rie代码的网站
  10. atomic 内存序_C++11的原子量与内存序浅析
  11. 候鸟算法在其他问题中应用时需要修改的代码
  12. 运用EXCEL RAND RANK INDEX函数制作抽奖器
  13. ubuntu 16 打开 dmg 文件
  14. 工业控制电气非标自动化设计安装调试PLC编程电路电气外包行业的前景预测与分析
  15. MySQL-7 DDL约束 标识列 TCL事务控制语言 视图view
  16. 基于采样的规划算法之RRT家族(三):RRT*
  17. Verilog轮询仲裁器设计——Round Robin Arbiter
  18. MTK5G-MT6853(天玑720)
  19. itextpdf截取pdf文件为新文件
  20. java自定义统计报表_用Java报表工具FineReport制作人员统计报表

热门文章

  1. RTMP直播应用与延时分析
  2. c++日志文件中文显示乱码的问题及解决办法
  3. 怎么在github上的私人项目中添加成员?
  4. 每日两SQL(9),欢迎交流~
  5. 大剑无锋之已知后续遍历bfegcda,中序badefcg,前序是?【面试推荐】
  6. 面试题:聊聊Unix与Java的IO模型?
  7. java基础---IO转换流
  8. leetcode 978. Longest Turbulent Subarray | 978. 最长湍流子数组(Java)
  9. 【Java语法】DateFormat时间格式转化、java.util.Date和java.sql.Date之间的相互转化
  10. 走进Java中的持有对象(容器类)之一 容器分类