Preface
I haven't written blog for a long time. I'm getting lazier and lazier. I still need to change! Today I learned the animation effects that are likely to be applied to my work.
Design sketch
Implementation ideas
LoginActivity jumps to MainActivity through transition Animation:
- Determine the starting position coordinate of the animation in LoginActivity and pass it to MainActivity through intent.
- MainActivity gets the starting position of the animation to execute the animation. If LoginActivity needs to be finished, it will be finished at the end of MainActivity animation execution.
- The window background of MainActivity needs to be set as transparent, and the root layout background needs to be set as non transparent.
- At the end of animation execution, LoginActivity is destroyed and local broadcast mode is adopted.
Implementation code
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"); // Starting position 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()); // The main activity animation cannot be finished until it is finished // finish(); } @Override protected void onDestroy() { super.onDestroy(); if (receiver != null) { LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); } } }
MainActivity layout has two pictures, and the layout code is omitted.
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); // If the system version is above 5.0, perform transition animation 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); / / this will result in an error 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) { // Send turn off LoginActivity broadcast 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); } }
Main activity is configured with transparent theme
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>