属性动画案例:雅虎加载视差动画
来源:互联网 发布:系统数据流程图 编辑:程序博客网 时间:2024/05/21 06:31
实现效果:
这边其实是两个View,加载动画覆盖在需要进入的页面的上面
动画分为三种状态
1:一开始的小圆球旋转动画
2:小圆逃逸后再聚合动画
3:水波纹扩散动画
一、初始化基本参数
private void init(Context context) { //这边mCircleColors为六个小球的颜色 mCircleColors = context.getResources().getIntArray(R.array.splash_circle_colors); //画笔初始化 //消除锯齿 mPaint.setAntiAlias(true); mPaintBackground.setAntiAlias(true);//该Paint为加载动画白色背景墙 //设置样式---边框样式--描边 mPaintBackground.setStyle(Paint.Style.STROKE); mPaintBackground.setColor(mSplashBgColor); }
二、使用策略模式分别实现三种状态
private SplashState mState=null; private abstract class SplashState{ public abstract void drawSate(Canvas canvas); }
先定义好是要实现的策略类
1)旋转动画
/** * 1.旋转动画 * 控制各个小圆的坐标----控制小圆的角度变化------属性动画ValueAnimator */ private class RotateState extends SplashState{ public RotateState() { //1.动画的初始工作, 0~2π 圆周角的弧度数 mAnimator=ValueAnimator.ofFloat(0f,(float)(Math.PI*2)); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //计算某个时刻当前的角度是多少 mCurrentRotationAngle= (float) animation.getAnimatedValue(); invalidate(); } }); // 2.开启动画 mAnimator.setInterpolator(new LinearInterpolator()); mAnimator.setDuration(mRotationDuration); mAnimator.setRepeatCount(ValueAnimator.INFINITE); mAnimator.start(); } public void cancel(){ mAnimator.cancel(); } @Override public void drawSate(Canvas canvas) { //1.背景---擦黑板,涂成白色 drawBackground(canvas); //2.绘制小圆 drawCircles(canvas); } }
构造方法中初始化好旋转动画所需的属性动画
绘制小圆的方法
private void drawCircles(Canvas canvas) { //每个小圆之间的间隔角度2π/小圆的个数 float rotationAngel= (float) (2*Math.PI/mCircleColors.length); for (int i=0;i<mCircleColors.length;i++){ /* * x=r*cos(a)+centerX * y=r*sin(a)+centerY */ double angle=i*rotationAngel+mCurrentRotationAngle; //每个小圆i*间隔角度+旋转角度=当前小圆的真实角度 float cx= (float) (mCurrentRotationRadius*Math.cos(angle)+mCenterX); float cy= (float) (mCurrentRotationRadius*Math.sin(angle)+mCenterY); mPaint.setColor(mCircleColors[i]); canvas.drawCircle(cx,cy,mCircleRadius,mPaint); } }
1.首先先求出一个由六个小圆组成大圆之间它们之间的间隔角度为2π/小球个数
2.再根据属性动画mCurrentRotationAngle计算的旋转角度以及间隔角度算出当前小球的真实角度
3.mCenterX和mCenterY取的是屏幕宽高的一半,mCurrentRotationRadius为定义的大圆的半径
4.这样就算出了小圆的圆心坐标
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(mState==null){ //开启第一个动画,旋转动画 mState=new RotateState(); } //调用绘制方法 mState.drawSate(canvas); }
在onDraw开启第一个动画,并调用绘制方法开始无限循环的旋转小球,在主界面顶一个延迟来结束第一个动画进入第二个动画
private void startLoadData() { mHandler.postDelayed(new Runnable() { @Override public void run() { //数据加载完毕,进入主界面---》开启后面的两个动画 mSplashView.splashDisapper(); } },3000); }
自定义View中:
public void splashDisapper(){ //开启后面两个动画 //换模板if--换状态 if(mState!=null&&mState instanceof RotateState){ //结束旋转动画 RotateState rotateState= (RotateState) mState; rotateState.cancel(); post(new Runnable() { @Override public void run() { mState=new MergingState(); } }); } }
2)聚合动画
/** * 2.聚合动画 * 要素:大圆的半径不断地变大---》变小----》小圆的坐标 */ private class MergingState extends SplashState{ public MergingState() { //r~0的某个值 mAnimator=ValueAnimator.ofFloat(mRotationRadius,0); mAnimator.setDuration(mRotationDuration); mAnimator.setInterpolator(new OvershootInterpolator(10f)); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //某个时刻当前的大圆半径是多少? mCurrentRotationRadius= (float) animation.getAnimatedValue(); invalidate(); } }); mAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mState=new ExpandState(); } }); mAnimator.start(); } @Override public void drawSate(Canvas canvas) { //1.背景---擦黑板,涂成白色 drawBackground(canvas); //2.绘制小圆 drawCircles(canvas); } }
1.mRotationRadius大圆初始半径到0的值,加入插值器OvershootInterpolator(向前甩一定值后再回到原来位置)
2.当持续时间完成调用下一个动画,这边drawState中同样是需要画白色背景墙和小圆的,只是这个时候mCurrentRotationRadius大圆半径进行了变化
3)水波纹扩散动画
/** * 3.水波纹扩散动画 * 画一个空心圆,让它的画笔的粗细变成很大---不断地减少画笔的粗细 * 空心圆变化的范围:0~对角线/2 */ private class ExpandState extends SplashState{ public ExpandState() { //1200ms,计算某个时刻当前的大圆半径是多少?r~对角线一半的某个值 mAnimator=ValueAnimator.ofFloat(mCircleRadius,mDiagonalDist); mAnimator.setDuration(mRotationDuration); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mHoleRadius= (float) animation.getAnimatedValue(); invalidate(); } }); mAnimator.start(); } @Override public void drawSate(Canvas canvas) { //1.背景---擦黑板,涂成白色 drawBackground(canvas); } }
1.第三个动画实现方式根据画一个空心圆,控制其stroWidth大小,不断减小实现扩散
2.mHoleRadius为空心圆的初始半径,这个时候处在第三状态的一开始所有的小球是已经聚集在一起的,所以初始半径这边根据属性动画mCircleRadius(小圆半径)到mDiagonalDist
3.mDiagonalDist:为屏幕对角线的一半,至于为什么是这个需要看一下drawBackground方法
private void drawBackground(Canvas canvas) { if(mHoleRadius>0f){//第三个动画开始执行 //得到画笔的宽度---对角线的一半-空心圆的半径 float stroWidth=mDiagonalDist-mHoleRadius; mPaintBackground.setStrokeWidth(stroWidth); //画圆的半径=空心圆的半径+画笔的宽度/2 float radius=mHoleRadius+stroWidth/2; canvas.drawCircle(mCenterX,mCenterY,radius,mPaintBackground); }else{//其他两个动画 canvas.drawColor(mSplashBgColor); } }
这样空心圆半径不断变大,stroWdith不断减少,圆半径随之改变,就实现了扩散的方法
- 属性动画案例:雅虎加载视差动画
- 视差动画
- 视差动画
- 仿雅虎视频加载动画
- ViewPager+属性动画 实现炫酷视差动画效果
- 自定义雅虎新闻闪屏加载动画
- Android动画案例(三)属性动画
- Parallax视差动画效果
- 视差动画引导界面
- ViewPager和视差动画
- 5.8_视差动画
- HTML5 Canvas 视差滚动动画
- android自定义view --视差动画
- ElementUI案例演示:导航、布局、加载动画
- ElementUI案例演示:导航、布局、加载动画
- ElementUI案例演示:导航、布局、加载动画
- ElementUI案例演示:导航、布局、加载动画
- ElementUI案例演示:导航、布局、加载动画
- C#你必须知道的25个基础概念
- 初来
- (M)Backtracking:47. Permutations II
- centos 6.5安装nodejs全记录
- java内存分配规则
- 属性动画案例:雅虎加载视差动画
- redis
- 欢迎使用CSDN-markdown编辑器
- 【模板】匈牙利算法 二分图最大匹配题模板
- 转了一篇能看明白的闭包
- 银联支付
- URAL 1960- Palindromes and Super Abilities (回文树)
- windows内网文件共享
- SQL 的四大连接方式