版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xingxtao/article/details/83691161
序言
好久没有写博客了,真是越来越懒了,还是要改变!今天学习了很有可能会应用到工作中的动画效果。
效果图
实现思路
LoginActivity 通过转场动画跳转到 MainActivity :
- 在 LoginActivity 中确定动画的开始位置坐标,并通过 intent 传递给 MainActivity。
- MainActivity 拿到动画起始位置执行动画,如果需要 finish 掉 LoginActivity ,在 MainActivity 动画执行结束时 finish 掉。
- MainActivity 的 window 背景需要设置为透明,并且 根布局 background 需要设置为非透明的。
- 动画执行结束销毁 LoginActivity ,采用本地广播方式。
实现代码
LoginActivity :
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/login_bg"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:onClick="click"
android:text="login" />
</RelativeLayout>
LoginActivity.java
public class LoginActivity extends AppCompatActivity {
public static final String POSITION_X = "position_x";
public static final String POSITION_Y = "position_y";
private BroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
registerBroadcast();
}
private void registerBroadcast() {
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (MainActivity.ACTION_CLOSE_LOGIN.equals(action)) {
finish();
}
}
};
IntentFilter filter = new IntentFilter(MainActivity.ACTION_CLOSE_LOGIN);
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void click(View view) {
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, view, "transtion");
// 起始位置
int startX = (int) (view.getX() + view.getWidth() / 2);
int startY = (int) (view.getY() + view.getHeight() / 2);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(POSITION_X, startX);
intent.putExtra(POSITION_Y, startY);
startActivity(intent, options.toBundle());
// 要等 MainActivity动画执行结束才能 finish 掉
// finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (receiver != null) {
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
}
}
MainActivity 布局就两张图片,布局代码省略。
MainActivity.java
public class MainActivity extends AppCompatActivity {
public static final String ACTION_CLOSE_LOGIN = "com.xing.activityanim.CLOSE_LOGIN";
private LinearLayout rootLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rootLayout = findViewById(R.id.rl_main_root);
Intent intent = getIntent();
final int startX = intent.getIntExtra(LoginActivity.POSITION_X, 0);
final int startY = intent.getIntExtra(LoginActivity.POSITION_Y, 0);
// 系统版本在 5.0 以上,执行转场动画
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
revealActivity(startX, startY);
// viewTreeObserver.removeOnGlobalLayoutListener(this); // 这样写会报错
rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
} else {
}
}
private void revealActivity(int x, int y) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
float finalRadius = Math.max(rootLayout.getWidth(), rootLayout.getHeight());
Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootLayout, x, y, 0, finalRadius);
circularReveal.setDuration(600);
circularReveal.setInterpolator(new LinearInterpolator());
circularReveal.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// 发送关闭 LoginActivity 广播
sendCloseBroadcast();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
circularReveal.start();
}
rootLayout.setVisibility(View.VISIBLE);
}
private void sendCloseBroadcast() {
Intent intent = new Intent(ACTION_CLOSE_LOGIN);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
其中 MainActivity 配置了透明主题
Androidmanifest.xml
<activity
android:name=".MainActivity"
android:theme="@style/TransparentTheme" />
styles.xml
<style name="TransparentTheme" parent="AppTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>