看了下5.0的过渡动画,效果确实蛮炫的,可惜我是4.4.2的,哎,享受不了啊,没钱买手机,穷啊
后来在格瓦拉app里面发现了这种过渡动画,4.4.2的也支持,那时候感觉,这么牛×啊(其实以下的都能支持),但是一直没见着好的源码看看,直到我看到了别人仿的一个知乎日报app,里面发现有这个功能,我就把他提取了出来,加上了自己所理解的一些注释,如有其它见解的,可以留言哦
- 废话不多说,老规矩,先上效果图
效果是真的蛮不错的,思路其实挺简单的,就是在第二个Activity界面上面再添加了一层动画效果的View,动画结束后就隐藏他,然后显示Activity界面
- MainActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void next(View v) {
int location[] = new int[2];
v.getLocationOnScreen(location);//将当前控件的坐标值赋给数组
location[0]+=v.getWidth()/2;//获取横坐标控件的中心位置
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("location", location);
startActivity(intent);
//关闭Activity启动的动画,目的是为了显示自己的动画
overridePendingTransition(0, 0);
}
public void next1(View v) {
int location[] = new int[2];
v.getLocationOnScreen(location);
location[0]+=v.getWidth()/2;
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("location", location);
startActivity(intent);
overridePendingTransition(0, 0);
}
activity_main.xml的文件就不写了,就是两个button,添加了两个onClick,一个next,一个next1。
- SecondActivity.java
public class SecondActivity extends Activity implements OnStateChangeListener {
private RevealBackgroundView revealBackgroundView;
private LinearLayout linea;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
linea = (LinearLayout) findViewById(R.id.linea);
revealBackgroundView = (RevealBackgroundView) findViewById(R.id.RevealBackgroundView);
setupRevealBackground(savedInstanceState);
}
private void setupRevealBackground(Bundle savedInstanceState) {
revealBackgroundView.setOnStateChangeListener(this);
//初始化时,当前的savedInstanceState为空
if (savedInstanceState == null) {
final int[] startLocation = getIntent()
.getIntArrayExtra("location");
// 初始化控件时的监听
revealBackgroundView.getViewTreeObserver().addOnPreDrawListener(
new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
revealBackgroundView.getViewTreeObserver().removeOnPreDrawListener(this);
// 设置单击坐标点的半径
revealBackgroundView.setCurrentRadius(50);
// 设置绘制填充画笔的颜色
revealBackgroundView.setFillPaintColor(0xff34A67B);
// 开启动画
revealBackgroundView.startFromLocation(startLocation);
return true;
}
});
} else {
// 完成动画
revealBackgroundView.setToFinishedFrame();
}
}
@Override
public void onStateChange(int state) {
// 如果当前状态完成,就显示底部布局,隐藏RevealBackgroundView
if (RevealBackgroundView.STATE_FINISHED == state) {
linea.setVisibility(View.VISIBLE);
revealBackgroundView.setVisibility(View.GONE);
}
}
}
- activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.anim.RevealBackgroundView
android:id="@+id/RevealBackgroundView "
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/linea"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是第二个页面"
android:textSize="50px" />
</LinearLayout>
</RelativeLayout>
重头戏View来了
- RevealBackgroundView.java
public class RevealBackgroundView extends View {
public static final int STATE_NOT_STARTED = 0;// 没有开始状态
public static final int STATE_FILL_STARTED = 1;// 填充满状态
public static final int STATE_FINISHED = 2;// 填充完成状态
// 在动画开始的时候速率比较慢,后面持续增加
private static final Interpolator INTERPOLATOR = new AccelerateInterpolator();
private static final int FILL_TIME = 600;// 动画时间600毫秒
private int state = STATE_NOT_STARTED;// 默认状态
private Paint fillPaint;// 画笔
private int currentRadius;// 半径
ObjectAnimator revealAnimator;
private int startLocationX;// 控件的x坐标值
private int startLocationY;// 控件的Y坐标值
private OnStateChangeListener onStateChangeListener;
public RevealBackgroundView(Context context) {
super(context);
init();
}
public RevealBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RevealBackgroundView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
fillPaint = new Paint();
fillPaint.setStyle(Paint.Style.FILL);
fillPaint.setColor(Color.WHITE);
}
// 设置画笔的颜色
public void setFillPaintColor(int color) {
fillPaint.setColor(color);
}
//开启动画
public void startFromLocation(int[] tapLocationOnScreen) {
changeState(STATE_FILL_STARTED);
startLocationX = tapLocationOnScreen[0];//传递过来view的x的RELATIVE_TO_SELF坐标值
startLocationY = tapLocationOnScreen[1];//传递过来view的y的RELATIVE_TO_SELF坐标值
// 动画标记为当前的半径currentRadius,值为RevealBackgroundView的0--width+height
revealAnimator = ObjectAnimator.ofInt(this, "currentRadius", 0,
getWidth() + getHeight()).setDuration(FILL_TIME);
revealAnimator.setInterpolator(INTERPOLATOR);
// 动画监听器
revealAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// 在动画结束的时候调用该方法
changeState(STATE_FINISHED);
}
});
revealAnimator.start();
}
// 当回调为true时,调用该方法,重新绘制当前界面
public void setToFinishedFrame() {
changeState(STATE_FINISHED);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// 在动画完成后直接画整个界面,不在让他继续扩散
if (state == STATE_FINISHED) {
canvas.drawRect(0, 0, getWidth(), getHeight(), fillPaint);
} else {
// 绘制点击控件位置扩散的圆圈
canvas.drawCircle(startLocationX, startLocationY, currentRadius,
fillPaint);
}
}
// 判断当前的状态
private void changeState(int state) {
if (this.state == state) {
return;
}
this.state = state;
// 将当前状态不停的回调,回调时判断一下当前是否完成,是的话就显示底部布局
if (onStateChangeListener != null) {
onStateChangeListener.onStateChange(state);
}
}
// 设置圆圈的半径时,重新调用onDraw,重新画圆
public void setCurrentRadius(int radius) {
this.currentRadius = radius;
invalidate();
}
public void setOnStateChangeListener(
OnStateChangeListener onStateChangeListener) {
this.onStateChangeListener = onStateChangeListener;
}
public static interface OnStateChangeListener {
void onStateChange(int state);
}
}
整个效果都是RevealBackgroundView来支持,代码也不是太多,很棒吧^-^
题外话,2016/3/12要去润创驾校体检,15号考科目一,在此记录一下,good idea