Shared Element Activity Transition
Bài đăng này đã không được cập nhật trong 8 năm
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_width="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_width="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_width="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
All rights reserved