Drawable加入动画机制(一)

我们都知道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的机制写的三段式动画

Drawable加入动画机制(二)


你可能感兴趣的:(Drawable加入动画机制(一))