本系列文章一共5篇
誰說Android的動畫不廉價(一)之項目分層
誰說Android的動畫不廉價(二)之轉場動畫
誰說Android的動畫不廉價(三)之共享元素動畫
誰說Android的動畫不廉價(四)之元素動畫
誰說Android的動畫不廉價(五)之水波紋動畫
GitHub源碼
引言
本篇博文是基于上一篇博文誰說Android的動畫不廉價(四)之元素動畫的基礎上做的拓展。
目標效果圖
轉場動畫
前提說明
水波紋動畫通過ViewAnimationUtils.createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius);
創建。返回一個屬性動畫類Animator
。
-
view
: 水波紋動畫作用的View -
centerX
: 水波紋動畫開始的X坐標 -
centerY
:水波紋動畫開始的Y坐標 -
startRadius
: 水波紋開始時圓的半徑 -
endRadius
: 水波紋擴散半徑
編碼
布局文件
水波紋動畫布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/tool_bar" />
<ImageView
android:id="@+id/img1"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:src="@drawable/circle_yellow"
android:transitionName="share1" />
<TextView
android:id="@+id/target"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolBar"
android:padding="20dp"
android:text="水波紋動畫"
android:textSize="30sp" />
<ImageView
android:id="@+id/circle_orange"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:onClick="orange"
android:scaleX="0"
android:scaleY="0"
android:src="@drawable/circle_orange" />
<ImageView
android:id="@+id/circle_red"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_margin="10dp"
android:layout_toRightOf="@+id/circle_orange"
android:onClick="red"
android:scaleX="0"
android:scaleY="0"
android:src="@drawable/circle_red" />
<ImageView
android:id="@+id/circle_blue"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_margin="10dp"
android:layout_toLeftOf="@+id/circle_yellow"
android:onClick="blue"
android:scaleX="0"
android:scaleY="0"
android:src="@drawable/circle_blue" />
<ImageView
android:id="@+id/circle_yellow"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="10dp"
android:onClick="yellow"
android:scaleX="0"
android:scaleY="0"
android:src="@drawable/circle_yellow" />
</RelativeLayout>
MainActivity.java
public void circularAnimations(View v) {
View view = findViewById(R.id.img1);
/**
* view是用于共享元素toolbar上面那一點
* 希望達到從共享元素擴散的效果
*/
Intent intent = new Intent(this, CircularAnimationsActivity.class);
ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this, new Pair(view, view.getTransitionName()));
startActivity(intent, activityOptionsCompat.toBundle());
}
CircularAnimations.java
package demo.august1996.top.transitionanimationsdemo;
import android.animation.Animator;
import android.graphics.Color;
import android.transition.ChangeBounds;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionManager;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import demo.august1996.top.transitionanimationsdemo.Activity.ToolbarActivity;
public class CircularAnimationsActivity extends ToolbarActivity {
/**
* 產生水波紋的View
*/
TextView target;
/**
* Toolbar的那個圓點
*/
ImageView imageView;
/**
* 產生進入動畫效果的底部ImageView
*/
List<View> imageViewList = new ArrayList<>();
/**
* 可以產生動畫的ViewGroup
*/
ViewGroup container;
/**
* 藍色點的原始參數,用于位置移動后恢復位置
*/
RelativeLayout.LayoutParams originlParams;
@Override
protected String getToolbarTitle() {
return "水波紋動畫";
}
/**
* 初始化View和動畫
*/
@Override
protected void initView() {
container = (ViewGroup) findViewById(R.id.container);
target = (TextView) findViewById(R.id.target);
imageView = (ImageView) findViewById(R.id.img1);
imageViewList.add(findViewById(R.id.circle_orange));
imageViewList.add(findViewById(R.id.circle_blue));
imageViewList.add(findViewById(R.id.circle_yellow));
imageViewList.add(findViewById(R.id.circle_red));
getWindow().setSharedElementEnterTransition(new ChangeBounds());
getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
/**
* 當Toobar那個點到達Toolbar的指定個位置后,隱藏Toolbar的點并且在點的的位置產生水波紋動畫
* 同時觸發底部ImageView的動畫效果
* @param transition
*/
@Override
public void onTransitionEnd(Transition transition) {
int cx = imageView.getLeft() + imageView.getWidth() / 2;
int cy = imageView.getTop() + imageView.getHeight() / 2;
int startR = imageView.getWidth() / 2;
int endR = Math.max(mToolbar.getWidth() / 2, mToolbar.getHeight() / 2);
startCircularAnimation(mToolbar, cx, cy, startR, endR, Color.parseColor("#ffffe600"));
imageView.setVisibility(View.GONE);
//下面的方式是使每個View的動畫產生順序,時差200ms
int delay = 200;
for (int i = 0; i < imageViewList.size(); i++) {
View v = imageViewList.get(i);
v.animate()
.setStartDelay(delay * i)
.scaleX(1)
.scaleY(1)
.start();
}
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
}
@Override
protected int getContentViewID() {
return R.layout.activity_circular_animations;
}
@Override
protected boolean canBack() {
return true;
}
/**
* orange red yellow的原理一樣,只是產生動畫的坐標XY不一樣
*
* @param v
*/
public void orange(View v) {
int cx = target.getWidth() / 2;
int cy = target.getHeight() / 2;
int startR = v.getWidth() / 2;
int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ffffae00"));
}
public void red(View v) {
int cx = target.getWidth() / 2;
int cy = mToolbar.getBottom();
int startR = v.getWidth() / 2;
int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ffff3d00"));
}
public void yellow(View v) {
int cx = v.getLeft() + v.getWidth() / 2;
int cy = v.getTop() + v.getHeight() / 2;
int startR = v.getWidth() / 2;
int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ffffe600"));
}
/**
* 此處跟上面的區別僅僅是先進行元素動畫改變元素的位置
* 然后再開啟水波紋動畫
* 最后位置設置回原來位置
*
* @param v
*/
public void blue(final View v) {
Transition transition = TransitionInflater.from(CircularAnimationsActivity.this).inflateTransition(R.transition.changebounds_with_arcmotion);
transition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
int cx = target.getWidth() / 2;
int cy = target.getHeight() / 2;
int startR = v.getWidth() / 2;
int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
Animator animator = startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ff0095ff"));
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
v.setLayoutParams(originlParams);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
if (originlParams == null) {
originlParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
}
TransitionManager.beginDelayedTransition(container, transition);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(v.getWidth(), v.getHeight());
params.addRule(RelativeLayout.CENTER_IN_PARENT);
v.setLayoutParams(params);
}
/**
* 開啟一個水波紋動畫
*
* @param target 開啟的View
* @param cx 產生動畫的X坐標
* @param cy 產生動畫的Y坐標
* @param startR 水波紋起始半徑
* @param endR 水波紋擴散半徑
* @param color 水波紋顏色
* @return
*/
private Animator startCircularAnimation(final View target, int cx, int cy, int startR, int endR, final int color) {
Animator circularReveal = ViewAnimationUtils.createCircularReveal(target, cx, cy, startR, endR);
circularReveal.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
target.setBackgroundColor(color);
}
@Override
public void onAnimationEnd(Animator animator) {
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
circularReveal.start();
return circularReveal;
}
}
我們的效果圖
我們的效果圖