Shared Element Activity Transition
Tổng quan Thông thường, việc chuyển tiếp giữa các Activiy hay Fragment chỉ đơn thuần là ẩn các Activity/Fragment cũ đi và hiển thị cái mới lên, có thể kèm theo một số hiệu ứng như Activity/Fragment mới dần dần hiện ra ( Fade), trượt vào đè lên cái cũ ( Slide).... Hiệu ứng mặc định khi chuyển ...
Tổng quan
Thông thường, việc chuyển tiếp giữa các Activiy hay Fragment chỉ đơn thuần là ẩn các Activity/Fragment cũ đi và hiển thị cái mới lên, có thể kèm theo một số hiệu ứng như Activity/Fragment mới dần dần hiện ra ( Fade), trượt vào đè lên cái cũ ( Slide)....
Hiệu ứng mặc định khi chuyển Activity:
Tuy nhiên, có những trường hợp mà một phần tử xuất hiện ở cả hai Activity/Fragment cũ và mới, và việc share chúng khi chuyển tiếp sẽ tạo cho người dùng cảm giác nối tiếp giữa cái cũ và cái mới.
Việc chuyển tiếp kiểu này cũng khiến cho mắt người cảm thấy mượt mà, liền mạch hơn.
Shared Elements Transition với Activity
Cần lưu ý là Shared Elements Transition chỉ hoạt động với Android 5.0 ( API level 21) trở lên và sẽ bị mặc định bỏ qua với các API level thấp hơn.
1. Thêm Window Content Transitions
Thêm Window Content Transitions vào file styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:windowContentTransitions">true</item> ... </style>
2. Gán chung một Transition Name
Sử dụng android:transitionName để gán một Transition Name chung cho phần tử cần share ở cả 2 layout.
Ví dụ ở MainActivity.xml:
<android.support.v7.widget.CardView ...> <ImageView android:id="@+id/ivProfile" android:transitionName="profile" android:scaleType="centerCrop" android:layout_awidth="match_parent" android:layout_height="160dp" /> ... </android.support.v7.widget.CardView>
Và ở DetailActivity.xml:
<LinearLayout ...> <ImageView android:id="@+id/ivProfile" android:transitionName="profile" android:scaleType="centerCrop" android:layout_awidth="match_parent" android:layout_height="380dp" /> ... </LinearLayout>
Start Activity
Start activity đối tượng và truyền cho nó một Bundle của những phần tử cần share.
Intent intent = new Intent(this, DetailsActivity.class); intent.putExtra(DetailsActivity.EXTRA_CONTACT, contact); ActivityOptionsCompat options = ActivityOptionsCompat. makeSceneTransitionAnimation(this, (View)ivProfile, "profile"); startActivity(intent, options.toBundle());
Để đảo ngược lại hiệu ứng chuyển tiếp khi tắt layout thứ hai, ta dùng Activity.supportFinishAfterTransition() thay vì Activity.finish().
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: supportFinishAfterTransition(); return true; } return super.onOptionsItemSelected(item); }
4. Share nhiều phần tử
Ta cũng có thể tạo hiệu ứng như vậy với nhiều phần tử trong một layout. Cách làm khá đơn giản, chỉ cần gán Transition Name khác nhau cho chúng và một ít code tương tự như sau:
Intent intent = new Intent(context, DetailsActivity.class); intent.putExtra(DetailsActivity.EXTRA_CONTACT, contact); Pair<View, String> p1 = Pair.create((View)ivProfile, "profile"); Pair<View, String> p2 = Pair.create(vPalette, "palette"); Pair<View, String> p3 = Pair.create((View)tvName, "text"); ActivityOptionsCompat options = ActivityOptionsCompat. makeSceneTransitionAnimation(this, p1, p2, p3); startActivity(intent, options.toBundle());
Lưu ý: nhớ chọn import là android.support.v4.util.Pair thay vì android.util.Pair.
Shared Elements Transition với Fragment
Cách làm cũng khá tương tự như trên.
1. Gán chung một Transition Name
<android.support.v7.widget.CardView ...> <ImageView android:id="@+id/ivProfile" android:transitionName="profile" android:scaleType="centerCrop" android:layout_awidth="match_parent" android:layout_height="160dp" /> ... </android.support.v7.widget.CardView>
2. Tạo ra Transition
Tạo thêm một transition tên change_image_transform.xml trong folder res/transition:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeImageTransform /> </transitionSet>
3. Tạo hiệu ứng chuyển tiếp trong FragmentTransaction
// Tạo thực thể của mỗi fragment FirstFragment fragmentOne = ...; SecondFragment fragmentTwo = ...; // Kiểm tra xem có phải phiên bản 5.0 trở lên ko. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Inflate transitions Transition changeTransform = TransitionInflater.from(this). inflateTransition(R.transition.change_image_transform); Transition explodeTransform = TransitionInflater.from(this). inflateTransition(android.R.transition.explode); // Cài đặt hiệu ứng chuyển tiếp khi thoát khỏi fragment thứ nhất fragmentOne.setSharedElementReturnTransition(changeTransform); fragmentOne.setExitTransition(explodeTransform); // Cài đặt hiệu ứng chuyển tiếp khi bật fragment thứ hai fragmentTwo.setSharedElementEnterTransition(changeTransform); fragmentTwo.setEnterTransition(explodeTransform); // Phần tử cần share ở fragment thứ nhất ImageView ivProfile = (ImageView) findViewById(R.id.ivProfile); // Replace fragment thứ hai FragmentTransaction ft = getFragmentManager().beginTransaction() .replace(R.id.container, fragmentTwo) .addToBackStack("transaction") .addSharedElement(ivProfile, "profile"); // Apply transaction ft.commit(); } else { // Code để chạy trên các phiên bản thấp hơn }
Một số nguồn khác để tham khảo thêm về Shared Element Transition.
- Fragment Transitions Detailed Tutorial
- Android Authority article
- Fragment transitions with shared elements
- Repo với code mẫu
- Một vài code mẫu
Nguồn: Codepath