Android Activity 轉場動畫

序言

好久沒有寫博客了,真是越來越懶了,還是要改變!今天學習了很有可能會應用到工作中的動畫效果。

效果圖

實現思路

LoginActivity 通過轉場動畫跳轉到 MainActivity :

  1. 在 LoginActivity 中確定動畫的開始位置座標,並通過 intent 傳遞給 MainActivity。
  2. MainActivity 拿到動畫起始位置執行動畫,如果需要 finish 掉 LoginActivity ,在 MainActivity 動畫執行結束時 finish 掉。
  3. MainActivity 的 window 背景需要設置爲透明,並且 根佈局 background 需要設置爲非透明的。
  4. 動畫執行結束銷燬 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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章