Android自定义View新年烟花、祝福语横幅动画

 更新时间:2018年01月24日 09:13:38   作者:匆忙拥挤repeat  
这篇文章主要为大家详细介绍了Android自定义View新年烟花、祝福语横幅动画,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

新年了,项目中要作个动画,整体要求实现彩带乱飞,烟花冲天而起,烟花缩放,小鸡换图,小鸡飘移,横幅裁剪、展开等动画效果,全局大量使用了属性动画来实现。

如下效果图:

我在实现过程中,横幅的裁剪计算,捣腾了比较久的时间,初版采用属性动画计算float的一个比率值,来配合每一帧的裁剪绘制,如下代码:

private static class RollView extends View { 
 private Bitmap mBitmap; 
 private Rect mSrc; 
 private Rect mDst; 
 private int mRollWidth = 60; 
 private float mRate; 
 private boolean mIsStopAnim; 
 
 public RollView(Context context) { 
  super(context); 
  mSrc = new Rect(); 
  mDst = new Rect(); 
 } 
 @Override 
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
  super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
 } 
 
 @Override 
 protected void onDraw(Canvas canvas) { 
  if (mBitmap == null) return; 
 
  drawFromMiddleByFloatCompute(canvas); 
 
 } 
 
 private void drawFromMiddleByFloatCompute(Canvas canvas) { 
  /* 
  以下src 都需要加上mBitmap. 的前缀,, 因从drawable拿到的是原始图片宽高 
  而适配时,可能view的宽高比 drawable的宽高还小或大 
  */ 
  final float rate = mRate; 
 
  mSrc.left = 0; 
  mSrc.top = 0; 
  mSrc.right = mRollWidth; 
  mSrc.bottom = mBitmap.getHeight(); 
 
  mDst.left = (int) ((getWidth() / 2 - mRollWidth) - (getWidth() / 2 - mRollWidth) * rate); 
  mDst.top = 0; 
  mDst.right = mDst.left + mRollWidth + 1;//因精度问题,这里强制+1 
  mDst.bottom = getHeight(); 
  canvas.drawBitmap(mBitmap, mSrc, mDst, null); 
 
  //中间 
  int sw = (int) ((mBitmap.getWidth() - mRollWidth * 2) * rate); 
  mSrc.left = mBitmap.getWidth() / 2 - sw / 2; 
  mSrc.top = 0; 
  mSrc.right = mSrc.left + sw; 
  mSrc.bottom = mBitmap.getHeight(); 
 
  int dw = (int) ((getWidth() - mRollWidth * 2) * rate); 
  mDst.left = getWidth() / 2 - dw / 2; 
  mDst.top = 0; 
  mDst.right = mDst.left + dw; 
  mDst.bottom = getHeight(); 
  canvas.drawBitmap(mBitmap, mSrc, mDst, null); 
 
  //右边 
  mSrc.left = mBitmap.getWidth() - mRollWidth; 
  mSrc.top = 0; 
  mSrc.right = mBitmap.getWidth(); 
  mSrc.bottom = mBitmap.getHeight(); 
 
  mDst.left = (int) (getWidth() / 2 + (getWidth() / 2 - mRollWidth) * rate); 
  mDst.top = 0; 
  mDst.right = mDst.left + mRollWidth; 
  mDst.bottom = getHeight(); 
 
  canvas.drawBitmap(mBitmap, mSrc, mDst, null); 
 } 
 
 public void setRes(int resId) { 
  mBitmap = getBitmapFromLocal(resId); 
 } 
 
 @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) 
 public void startFloatComputeAnim() { 
  /* 
  如果有float获取比率值,从而计算出相应的坐标值,那么可能由于最终在转成Rect的坐标时, 
  float to int ,有精度的损失:1个px 而引起效果的不理想 
  */ 
  ValueAnimator animator = ValueAnimator.ofFloat(0, 1); 
  animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
  @Override 
  public void onAnimationUpdate(ValueAnimator animation) { 
   if (mIsStopAnim) { 
   animation.cancel(); 
   return; 
   } 
   mRate = (float) animation.getAnimatedValue(); 
   invalidate(); 
 
  } 
  }); 
  animator.setDuration(2000); 
  animator.start(); 
 } 
 
 public void stopAnim() { 
  mIsStopAnim = true; 
 } 
 } 

> 因float转int有一个精度损失的问题,所以在计算中强制加上了1px(代码中有);
这样虽然解决了有1px没有绘制的问题,但是会发生绘制时不够平滑,而出现抖动的情形(在某些devices上)
所以最好还是不要使用float来计算
> 后来,同事猜想使用一个固定int值 来参与计算,可能可以解决上述问题:
比如每秒30帧,这里动画时长2秒,即共30*2=60帧;
图片宽度、左画轴、右画轴  对  60帧数 做相应的除法及其他计算,可得出一个单帧中 它们应该运动的x距离
> 之后,我又想了一种,使用一个属性动画,来计算出从0到getWidth()之间的 动画值,
从而通过计算,使得横幅从左向右拉开, 如下:

代码就不整体开源了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android studio 出现错误Run with --stacktrace option to get the stack trace. Run with --info or --debu

    Android studio 出现错误Run with --stacktrace option to get the s

    这篇文章主要介绍了 Android studio 出现错误Run with --stacktrace option to get the stack trace. Run with --info or --debu的相关资料,需要的朋友可以参考下
    2016-11-11
  • Android高仿京东垂直循环滚动新闻栏

    Android高仿京东垂直循环滚动新闻栏

    通过自定义的LinearLayout,并且textView能够循环垂直滚动,而且条目可以点击,显示区域最多显示2个条目,并且还有交替的属性垂直移动的动画效果,通过线程来控制滚动的实现
    2016-03-03
  • Android 手机浏览器调试使用Chrome进行调试实例详解

    Android 手机浏览器调试使用Chrome进行调试实例详解

    这篇文章主要介绍了Android 手机浏览器调试使用Chrome进行调试实例详解的相关资料,这里提供了实例,需要的朋友可以参考下
    2016-12-12
  • 深入理解Android中Scroller的滚动原理

    深入理解Android中Scroller的滚动原理

    今天给大家讲解的是Scroller类的滚动实现原理,可能很多朋友不太了解该类是用来干嘛的,但是研究Launcher的朋友应该对他很熟悉,Scroller类是滚动的一个封装类,可以实现View的平滑滚动效果,而我们今天就来探究一下为什么Scroller能够实现平滑滚动。
    2016-08-08
  • 详解Android ViewCompat的作用

    详解Android ViewCompat的作用

    这篇文章主要介绍了详解Android ViewCompat的作用的相关资料,需要的朋友可以参考下
    2017-07-07
  • Android中判断网络连接是否可用及监控网络状态

    Android中判断网络连接是否可用及监控网络状态

    获取网络信息需要在AndroidManifest.xml文件中加入相应的权限,接下来详细介绍Android中判断网络连接是否可用及监控网络状态,感兴趣的朋友可以参考下
    2012-12-12
  • Android设计模式系列之工厂方法模式

    Android设计模式系列之工厂方法模式

    工厂方法模式,往往是设计模式初学者入门的模式,的确,有人称之为最为典型最具启发效果的模式。接下来通过本文给大家介绍Android设计模式系列之工厂方法模式,感兴趣的朋友一起学习吧
    2016-09-09
  • Android EditText实现分割输入内容

    Android EditText实现分割输入内容

    这篇文章主要为大家详细介绍了Android EditText实现分割输入内容的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • Android编程之四种Activity加载模式分析

    Android编程之四种Activity加载模式分析

    这篇文章主要介绍了Android编程之四种Activity加载模式,简要分析了Android编程中涉及的Activity的四种加载模式,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-01-01
  • Ubuntu中为Android实现Application Frameworks层增加硬件访问服务

    Ubuntu中为Android实现Application Frameworks层增加硬件访问服务

    本文主要介绍Android实现 Application Frameworks层增加硬件访问服务,这里对实现增加硬件访问服务的功能做出了详细的工作流程,并提供示例代码,有需要的小伙伴参考下
    2016-08-08

最新评论