圆形揭示动画在很多情况下都可以使用,比如说转场、打开popupwidow和覆盖一层新的view。

官方也提供了一个类专门提供这个动画的封装:ViewAnimationUtils.createCircularReveal(View view,            int centerX,  int centerY, float startRadius, float endRadius)

然而这个方法必须api 5.0以上才能使用,既然如此不如自己动手造轮子。

思路:

1.只负责显示的范围,所以继承自FrameLayout,具体显示的内容由Child负责。

2.如何控制child显示的区域?在dispatchDraw中调用canvas.clipPath(Path path)把需要显示的区域裁剪出来。

3.如何显示圆?mCirclePath.reset();

mCirclePath.addCircle(float x, float y, float radius, Direction dir)

4.动画用ValueAnimator。

具体流程:/**

* 开始揭示动画

* @param x 动画开始位置的x值

* @param y 动画开始位置的y值

*/

public void revealLayout(int x, int y){

mCenterX = x;

mCenterY = y;

computeFarthest();

computeVisibleRegion();        if (mAnimator == null) {

mAnimator = ValueAnimator.ofFloat(0,1);

mAnimator.setDuration(DEFAULT_ANIMATION_DURATION);

mAnimator.setInterpolator(new DecelerateInterpolator());

mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {                @Override

public void onAnimationUpdate(ValueAnimator animation) {

mAnimationValue = (float) animation.getAnimatedValue();

postInvalidate((int) (mVisibleRectF.left*mAnimationValue),(int) (mVisibleRectF.top*mAnimationValue)

,(int) (mVisibleRectF.right*mAnimationValue),(int) (mVisibleRectF.bottom*mAnimationValue));

}

});

}

mAnimator.start();

}

开始动画,传入动画开始的坐标值xy。

computeFarthest()计算动画开始点与Layout四个角的最远距离,即圆形为最大时的半径。

computeVisibleRegion()计算圆形显示区域的外界矩形,用于postInvalidate()时指定刷新的区域,减少绘制开销。@Override

protected void dispatchDraw(Canvas canvas) {        if (mAnimationValue == 0){            return;

}

canvas.save();

mCirclePath.reset();

mCirclePath.addCircle(mCenterX,mCenterY,mFarthest*mAnimationValue, Path.Direction.CW);

canvas.clipPath(mCirclePath);        super.dispatchDraw(canvas);

canvas.restore();

}

动画开始前不绘制Layout里的内容,动画开始后根据mAnimationValue的值改变圆形的大小。mFarthest为之前通过computeFarthest()计算出来的结果。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐