我们都知道Android有原生的Drawable动画,也就是由一组Drawable组成的帧动画
但如果想要给TextView中的Drawable加入动画,用这个方法显然是行不通的
我刚开始想用属性动画去做,但设好传进去后还是没有动画效果(如果有用属性动画实现的大神求留言)
于是在GitHub上找到了这个例子,它实现了Drawable的自定义Scale动画:点击打开链接
在这篇文章里来分析下这个例子的原理
首先它重写了Draw,这是实现动画的核心,先贴代码
public void draw(Canvas canvas)
{
final AnimationScaleState st = mState;
if(st.mDrawable == null){
return;
}
final Rect bounds = (st.mUseBounds ? getBounds() : mTmpRect);
int saveCount = canvas.save();
canvas.scale(st.mScale, st.mScale,
bounds.left + bounds.width() / 2,
bounds.top + bounds.height() / 2);
st.mDrawable.draw(canvas);
canvas.restoreToCount(saveCount);
if(st.mAnimating){
long animTime = AnimationUtils.currentAnimationTimeMillis();
st.mAnimation.getTransformation(animTime, st.mTransformation);
float transformation = st.mTransformation.getAlpha();
st.mScale = (st.mMinScale + (st.mMaxScale - st.mMinScale)
* (st.mInvert ? (1.0f - transformation) : transformation));
invalidateSelf();
}
}
其中的st是自定义的AnimationScaleState,用来存储Drawable的各种参数和状态
每次调Drawable的draw之前都会给Canvas设下Scale
当st.mAnimating为true时,都会重新计算当前的Scale,这里它用了个巧思:
在st里定义了一个(0.0f, 1.0f)的AlphaAnimation,取它的transformation和其他参数来实现Drawable本身的渐变等效果
每次计算过后,就会调invalidate进行重绘,从而实现Scale动画
再看看调用动画的过程:
@Override
public void start()
{
if(mState.mAnimating){
return;
}
if(mState.mInterpolator == null){
mState.mInterpolator = new LinearInterpolator();
}
if(mState.mTransformation == null){
mState.mTransformation = new Transformation();
}
else{
mState.mTransformation.clear();
}
if(mState.mAnimation == null){
mState.mAnimation = new AlphaAnimation(0.0f, 1.0f);
}
else{
mState.mAnimation.reset();
}
mState.mAnimation.setRepeatMode(Animation.REVERSE);
mState.mAnimation.setRepeatCount(Animation.INFINITE);
mState.mAnimation.setDuration(mState.mDuration);
mState.mAnimation.setInterpolator(mState.mInterpolator);
mState.mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME);
mState.mAnimating = true;
invalidateSelf();
}
简单来说就是把需要的参数是空的都设一设,然后把mAnimating置true,invalidate()
调用方法是在外层new好Drawable之后,传入TextView,再调用start(),即可实现Scale动画效果
这个Demo实现的是一直跳动的心的效果
但我在Demo中测试时发现了几个问题
1. 由于这个Demo里的效果是持续的,所以他没有考虑动画停止机制,只写了个stop()函数,对于只需要调用一次的动画,在动画开始后需要选择合适的调用时机,不实用
2. 动画缺少灵活性,我想弄个三段式动画
在下篇文章中,我将介绍我根据这个Demo的机制写的三段式动画