Android Activity transition animation

Keywords: Mobile Android xml Java encoding

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:

  1. Determine the starting position coordinate of the animation in LoginActivity and pass it to MainActivity through intent.
  2. 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.
  3. The window background of MainActivity needs to be set as transparent, and the root layout background needs to be set as non transparent.
  4. 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>

Posted by barteelamar on Tue, 10 Dec 2019 20:40:12 -0800