新年了,项目中要作个动画,如下效果图:
整体要求实现:彩带乱飞,烟花冲天而起,烟花缩放,小鸡换图,小鸡飘移,横幅裁剪、展开等动画效果,全局大量使用了属性动画来实现。
我在实现过程中,横幅的裁剪计算,捣腾了比较久的时间,初版采用属性动画计算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,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,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仿QQ聊天撒花特效 很真实Android营造雪花和雨滴浪漫效果 总结以上是内存溢出为你收集整理的Android自定义View新年烟花、祝福语横幅动画全部内容,希望文章能够帮你解决Android自定义View新年烟花、祝福语横幅动画所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)