高仿扫描附近好友效果
高仿扫描附近好友效果。
先来看效果:
AnimatorSet是一个集合动画,允许对控件设置一系列的动画。在AnimatorSet里可以指定动画的播放顺序、是否一起播放或者是否延迟播放。
向AnimatorSet添加动画有两种不同的方法,其一是调用playTogether()或playSequentially()方法来一次性添加一组动画,其二是播放(Animator)可以与Builder类一个一个添加动画。
常用的API
play(Animator anim):添加一个动画,并返回AnimatorSet.Builder
playSequentially(List items):添加一组动画,播放顺序为一一播放
playSequentially(Animator… items):添加一组动画,播放顺序为一一播放
playTogether(Collection items):添加一组动画,播放顺序为一起播放
playTogether(Animator… items):添加一组动画,播放顺序为一起播放
其中save:用来保存Canvas画布状态。save后,我们可以调用Canvas的平移、放缩、旋转等操作。
restore:用来恢复Canvas画布之前的保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
对canvas中特定元素的旋转平移等操作实际上是对整个画布进行了操作,如果不对canvas进行save以及restore操作,那么每一次绘图都会在上一次的基础上进行操作,很容易导致错位。
可以理解为save是入栈,restore是出栈。
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(3 * 1000);
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.playTogether(mValueAnimator, mValueAnimator2);
animatorSet.start();
完整源码:
public class RippleView extends View {
private Bitmap mBitmap1, mBitmap2, mBitmap3;
private Matrix matrix1, matrix2;
private Paint mPaint1, mPaint2;
private int mDegrees;
private float mFactor = 0.7f;
private ValueAnimator mValueAnimator, mValueAnimator2;
public RippleView(Context context) {
this(context, null);
}
public RippleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RippleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context ctx) {
mBitmap1 = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ripple_bg_1);
mBitmap2 = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ripple_bg_2);
mBitmap3 = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ripple_bg_3);
matrix1 = new Matrix();
matrix2 = new Matrix();
mPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
/** * 旋转动画 */
mValueAnimator = ValueAnimator.ofInt(0, 360);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mDegrees = (int) animation.getAnimatedValue();
postInvalidate();
}
});
mValueAnimator.setRepeatCount(Animation.INFINITE);
/** * 波纹动画 */
mValueAnimator2 = ValueAnimator.ofFloat(0.7f, 1.0f);
mValueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mPaint2.setAlpha((int) (255 - 180 * animation.getAnimatedFraction()));
mFactor = (float) animation.getAnimatedValue();
}
});
mValueAnimator2.setRepeatCount(Animation.INFINITE);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(3 * 1000);
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.playTogether(mValueAnimator, mValueAnimator2);
animatorSet.start();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mBitmap3.getWidth(), mBitmap2.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
/**
* 旋转效果
*/
canvas.save();
canvas.translate(getWidth() / 2 - mBitmap1.getWidth() / 2, getHeight() / 2 - mBitmap1.getHeight() / 2);
matrix1.setRotate(mDegrees, mBitmap1.getWidth() / 2, mBitmap1.getHeight() / 2);
canvas.drawBitmap(mBitmap1, matrix1, mPaint1);
canvas.restore();
/**
* 波纹效果
*/
canvas.translate(getWidth() / 2 - mBitmap2.getWidth() / 2, getHeight() / 2 - mBitmap2.getHeight() / 2);
matrix2.setScale(mFactor, mFactor, mBitmap2.getWidth() / 2, mBitmap2.getHeight() / 2);
canvas.drawBitmap(mBitmap2, matrix2, mPaint2);
}
}
【END】
觉得此文不错
请随手转发到朋友圈
每一位技术人成长都不易,感谢有你
往期精选推荐
程序员32岁前跳槽大多数看薪资,那里福利好去那里,32岁后请慎重
分享职场攻略、技术心得和创业资源
更多精彩内容,请长按识别关注