android精美ui动画界面,Android UI 篇- 实现一个揭露动画

一、应用场景

1、 先上效果图:

ab8a145e9b4a

效果图

2、 应用场景分析:

适用于 Activity 界面跳转

适用于 View 的切换

支持所有 View 布局的动画效果

3、代码使用(非常简洁好用):

在你需要做动画的布局上,套上RevealAnimationLayout 就可以了,支持套任何布局!!!

android:id="@+id/animat_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content"

>

android:layout_width="match_parent"

android:layout_height="400dp"

android:layout_marginLeft="50dp"

android:layout_marginRight="50dp"

android:scaleType="centerCrop"

android:src="@mipmap/test"/>

// java 代码中,调用

mClipAnimationLayout.startAnimal(RevealAnimationLayout.AnimaType.Circle);

二、流程分析

1、android 5.0 其实已经拥有对应的接口 ViewAnimationUtils.createCircularReveal ,然而还是有一定的局限性:

只能再 android 5.0 上使用

只提供圆形的揭露效果

也没有提供拓展其他图形接口

2、对于这个效果,我们只能自定义 View,来实现。思路步骤如下:

做一个空父布局,提供出去,可以套任何布局

在空的布局对套进来的子布局操作。

要在 draw 这个函数下手,并且要在 super.draw() 之后去做剪裁,目的是确保子布局先 draw 完。

使用画笔 setXfermode 去实现这个动画效果。先用 Path 画出圆形/矩形,重叠在画布上面,取出重叠的 View 。

3、我们复写draw函数,对draw函数进行重写。回顾一下draw 函数的流程:

ab8a145e9b4a

绘制流程

可以重写的只有:

draw

onDraw (只能绘制自己,绘制不了内部子布局)

dispatchDraw

综上:满足条件的只有 draw 和 dispatchDraw重写这两个都可以实现,譬如下面模拟代码:

@Override

public void draw(Canvas canvas) {

canvas.saveLayer(mLayer, null, Canvas.ALL_SAVE_FLAG);

super.draw(canvas); //自身绘制在canvas上,子布局绘制在canvas

onClipDraw(canvas); //上面代码绘制完毕,再对整个canvas进行操作

canvas.restore();

}

@Override

protected void dispatchDraw(Canvas canvas) {

canvas.saveLayer(mLayer, null,Canvas.ALL_SAVE_FLAG);

/**

*子布局绘制在canvas,自身还没有绘制完毕,还要跑绘制

*drawAutofilledHighlight-onDrawForeground-drawDefau*ltFocusHighlight。不过没关系我们只要对子布局操作

*/

super.dispatchDraw(canvas);

onClipDraw(canvas); //子布局绘制完毕,再对canvas进行操作

canvas.restore()

}

三、代码实现

1、首先开启一个动画器,拿到动画执行的 百分比值 :mAnimatorValue

/**

* 初始化动画类

*/

private void initAnimator() {

mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

//拿到动画的执行的百分比mAnimatorValue

mAnimatorValue = (float) animation.getAnimatedValue();

invalidate();

}

};

mStartingAnimator = new ValueAnimator().setDuration(defaultDuration);

mStartingAnimator.setInterpolator(new AccelerateInterpolator());

mStartingAnimator.addUpdateListener(mUpdateListener);

}

/**

* 开启动画

* @param animaType 动画类型

*/

public void startAnimal(AnimaType animaType) {

this.mAnimaType = animaType;

setVisibility(View.VISIBLE);

mStartingAnimator.cancel();

if(mAnimaType == AnimaType.BackCircle ||

mAnimaType == AnimaType.BackLeftRight ||

mAnimaType == AnimaType.BackUpDown ) {

mStartingAnimator.setFloatValues(1,0);

} else {

mStartingAnimator.setFloatValues(0,1);

}

mStartingAnimator.start();

}

2、我们再来生成个剪裁路径 mClipPath(Path类),需要通过百分比 mAnimatorValue 计算出 mClipPath 需要添加半径为多大的圆 :

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mLayer.set(0, 0, w, h);

refreshRegion(this);

}

public void refreshRegion(View view) {

int w = (int) mLayer.width();

int h = (int) mLayer.height();

RectF areas = new RectF();

areas.left = view.getPaddingLeft();

areas.top = view.getPaddingTop();

areas.right = w - view.getPaddingRight();

areas.bottom = h - view.getPaddingBottom();

mClipPath.reset();

PointF center = new PointF(w / 2, h / 2);

if (mAnimaType == AnimaType.Circle || mAnimaType == AnimaType.BackCircle) {

float d = (float) Math.hypot(areas.width(), areas.height());

//通过动画的百分比mAnimatorValue,计算出圆的半径

float r = d / 2 * mAnimatorValue;

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) {

//这里添加了一个圆

mClipPath.addCircle(center.x, center.y, r, Path.Direction.CW);

mClipPath.moveTo(0, 0); // 通过空操作让Path区域占满画布

mClipPath.moveTo(w, h);

} else {

float y = h / 2 - r;

mClipPath.moveTo(areas.left, y);

mClipPath.addCircle(center.x, center.y, r, Path.Direction.CW);

}

}

}

3、最后这里我们对 Draw 下手,把生成好的 mClipPath,画到 canvas (整个已经绘制到的布局),使用 PorterDuff.Mode.DST_OUT 拿出 和圆重叠的部分。(其中使用了一个小技巧兼容 android 9.0 详细看下面代码)

@Override

public void draw(Canvas canvas) {

canvas.saveLayer(mLayer, null, Canvas.ALL_SAVE_FLAG);

super.draw(canvas);

onClipDraw(canvas);

canvas.restore();

}

public void onClipDraw(Canvas canvas) {

mPaint.setColor(Color.WHITE);

mPaint.setStyle(Paint.Style.FILL);

mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

mOpClipPath.reset();

mOpClipPath.addRect(0, 0, mLayer.width(), mLayer.height(), Path.Direction.CW);

//取反,因为 android 9.0 不对 paint 以外(paint 自身有指定区域,这里在画笔上添加的区域是一个圆)的布局绘制

mOpClipPath.op(mClipPath, Path.Op.DIFFERENCE);

canvas.drawPath(mOpClipPath, mPaint);

}

代码很简单,就一个布局。可以用来实现 Activity 的跳转,界面部分 View 的切换。也极易拓展,建议大家下载下来看看。

最后鸣谢:gcssloop作者 给了我灵感。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值