Slide layar adalah transisi dari satu layar penuh ke layar lainnya dan umum digunakan dengan UI seperti
wizard penyiapan dan slideshow. Topik ini menunjukkan cara melakukan slide layar dengan objek
ViewPager2. Objek ViewPager2 dapat menganimasikan slide layar secara otomatis. Berikut adalah contoh
slide layar yang bertransisi dari satu layar konten ke layar berikutnya:
Untuk menggunakan ViewPager2, Anda perlu menambahkan beberapa
dependensi AndroidX ke
project Anda. Kemudian, ikuti langkah-langkah yang diuraikan di bagian berikut.
Membuat tampilan
Buat file tata letak yang akan digunakan nanti untuk konten fragmen. Anda juga perlu menentukan string untuk konten fragmen. Contoh berikut berisi tampilan teks yang menampilkan beberapa teks:
<!-- fragment_screen_slide_page.xml --> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView style="?android:textAppearanceMedium" android:padding="16dp" android:lineSpacingMultiplier="1.2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/lorem_ipsum" /> </ScrollView>
Membuat fragmen
Buat class
Fragment yang
menampilkan tata letak yang Anda buat dalam
metode
onCreateView(). Kemudian, Anda dapat membuat instance fragmen ini dalam aktivitas induk setiap kali Anda memerlukan
halaman baru untuk ditampilkan kepada pengguna:
Kotlin
import androidx.fragment.app.Fragment class ScreenSlidePageFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_screen_slide_page, container, false) }
Java
import androidx.fragment.app.Fragment; ... public class ScreenSlidePageFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return (ViewGroup) inflater.inflate( R.layout.fragment_screen_slide_page, container, false); } }
Menambahkan ViewPager2
Objek ViewPager2 memiliki gestur geser bawaan untuk beralih antarhalaman, dan
menampilkan animasi slide layar secara default, sehingga Anda tidak perlu membuat animasi sendiri.
ViewPager2 menggunakan objek FragmentStateAdapter sebagai suplai untuk halaman baru yang akan ditampilkan, sehingga FragmentStateAdapter menggunakan class fragmen yang Anda buat.
Untuk memulai, buat tata letak yang berisi objek ViewPager2:
<!-- activity_screen_slide.xml --> <androidx.viewpager2.widget.ViewPager2 xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" />
Buat aktivitas yang melakukan hal berikut:
- Menyetel tampilan konten menjadi tata letak dengan
ViewPager2. - Membuat class yang memperluas class abstrak
FragmentStateAdapterdan mengimplementasikan metodecreateFragment()untuk menyediakan instanceScreenSlidePageFragmentsebagai halaman baru. Anda harus mengimplementasikan metodegetItemCount()untuk adaptor pager, yang menampilkan jumlah halaman yang dibuat adaptor. Ada lima dalam contoh. - Mengaitkan
FragmentStateAdapterke objekViewPager2.
Kotlin
import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity ... /** * The number of pages (wizard steps) to show in this demo. */ private const val NUM_PAGES = 5 class ScreenSlidePagerActivity : FragmentActivity() { /** * The pager widget, which handles animation and allows swiping horizontally * to access previous and next wizard steps. */ private lateinit var viewPager: ViewPager2 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_screen_slide) // Instantiate a ViewPager2 and a PagerAdapter. viewPager = findViewById(R.id.pager) // The pager adapter, which provides the pages to the view pager widget. val pagerAdapter = ScreenSlidePagerAdapter(this) viewPager.adapter = pagerAdapter } override fun onBackPressed() { if (viewPager.currentItem == 0) { // If the user is currently looking at the first step, allow the system to handle // the Back button. This calls finish() on this activity and pops the back stack. super.onBackPressed() } else { // Otherwise, select the previous step. viewPager.currentItem = viewPager.currentItem - 1 } } /** * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in * sequence. */ private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) { override fun getItemCount(): Int = NUM_PAGES override fun createFragment(position: Int): Fragment = ScreenSlidePageFragment() } }
Java
import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; ... public class ScreenSlidePagerActivity extends FragmentActivity { /** * The number of pages (wizard steps) to show in this demo. */ private static final int NUM_PAGES = 5; /** * The pager widget, which handles animation and allows swiping horizontally to access previous * and next wizard steps. */ private ViewPager2 viewPager; /** * The pager adapter, which provides the pages to the view pager widget. */ private FragmentStateAdapter pagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_screen_slide); // Instantiate a ViewPager2 and a PagerAdapter. viewPager = findViewById(R.id.pager); pagerAdapter = new ScreenSlidePagerAdapter(this); viewPager.setAdapter(pagerAdapter); } @Override public void onBackPressed() { if (viewPager.getCurrentItem() == 0) { // If the user is currently looking at the first step, allow the system to handle the // Back button. This calls finish() on this activity and pops the back stack. super.onBackPressed(); } else { // Otherwise, select the previous step. viewPager.setCurrentItem(viewPager.getCurrentItem() - 1); } } /** * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in * sequence. */ private class ScreenSlidePagerAdapter extends FragmentStateAdapter { public ScreenSlidePagerAdapter(FragmentActivity fa) { super(fa); } @Override public Fragment createFragment(int position) { return new ScreenSlidePageFragment(); } @Override public int getItemCount() { return NUM_PAGES; } } }
Menyesuaikan animasi menggunakan PageTransformer
Untuk menampilkan animasi yang berbeda dari animasi slide layar default, terapkan antarmuka
ViewPager2.PageTransformer
dan berikan ke objek ViewPager2. Antarmuka ini mengekspos satu
metode,
transformPage().
Pada setiap titik dalam transisi layar, metode ini dipanggil sekali untuk setiap halaman yang terlihat—biasanya
hanya ada satu halaman yang terlihat—dan untuk halaman yang berdekatan di luar layar. Misalnya, jika halaman tiga
terlihat dan pengguna menarik ke arah halaman empat, transformPage() akan dipanggil untuk halaman dua,
tiga, dan empat di setiap langkah gestur.
Dalam penerapan transformPage(), Anda dapat membuat animasi slide kustom dengan menentukan halaman mana yang perlu diubah berdasarkan posisi halaman di layar. Dapatkan posisi halaman dari parameter position dari
metode transformPage().
Parameter position menunjukkan lokasi halaman tertentu yang terkait dengan
tengah layar. Parameter ini adalah properti dinamis yang berubah saat pengguna men-scroll
serangkaian halaman. Saat sebuah halaman mengisi layar, nilai posisinya adalah 0. Saat halaman
digambar di sisi kanan layar, nilai posisinya adalah 1. Jika pengguna men-scroll
setengah jalan antara halaman satu dan dua, halaman satu memiliki posisi -0.5, dan halaman dua memiliki
posisi 0.5. Berdasarkan posisi halaman di layar, Anda dapat membuat
animasi slide kustom dengan menetapkan properti halaman menggunakan metode seperti
setAlpha(),
setTranslationX(),
atau
setScaleY().
Jika Anda memiliki implementasi
PageTransformer,
panggil
setPageTransformer()
dengan implementasi Anda untuk menerapkan animasi kustom. Misalnya, jika Anda memiliki
PageTransformer bernama ZoomOutPageTransformer, Anda dapat menyetel animasi
kustom seperti ini:
Kotlin
val viewPager: ViewPager2 = findViewById(R.id.pager) ... viewPager.setPageTransformer(ZoomOutPageTransformer())
Java
ViewPager2 viewPager = findViewById(R.id.pager); ... viewPager.setPageTransformer(new ZoomOutPageTransformer());
Lihat bagian Zoom-out page transformer dan
Depth page transformer untuk mengetahui contoh
PageTransformer.
Transformer halaman zoom-out
Page transformer ini mengecilkan dan memudarkan halaman saat men-scroll di antara halaman yang berdekatan. Saat halaman mendekati bagian tengah, halaman akan kembali ke ukuran normalnya dan muncul secara bertahap.
ZoomOutPageTransformer.
Kotlin
private const val MIN_SCALE = 0.85f private const val MIN_ALPHA = 0.5f class ZoomOutPageTransformer : ViewPager2.PageTransformer { override fun transformPage(view: View, position: Float) { view.apply { val pageWidth = width val pageHeight = height when { position < -1 -> { // [-Infinity,-1) // This page is way off-screen to the left. alpha = 0f } position <= 1 -> { // [-1,1] // Modify the default slide transition to shrink the page as well. val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)) val vertMargin = pageHeight * (1 - scaleFactor) / 2 val horzMargin = pageWidth * (1 - scaleFactor) / 2 translationX = if (position < 0) { horzMargin - vertMargin / 2 } else { horzMargin + vertMargin / 2 } // Scale the page down (between MIN_SCALE and 1). scaleX = scaleFactor scaleY = scaleFactor // Fade the page relative to its size. alpha = (MIN_ALPHA + (((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA))) } else -> { // (1,+Infinity] // This page is way off-screen to the right. alpha = 0f } } } } }
Java
public class ZoomOutPageTransformer implements ViewPager2.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0f); } else if (position <= 1) { // [-1,1] // Modify the default slide transition to shrink the page as well. float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); } // Scale the page down (between MIN_SCALE and 1). view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // Fade the page relative to its size. view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0f); } } }
Transformer halaman depth
Page transformer ini menggunakan animasi slide default untuk menggeser halaman ke kiri, sekaligus menggunakan animasi "kedalaman" untuk menggeser halaman ke kanan. Animasi kedalaman ini memudarkan halaman dan memperkecil skalanya secara linear.
DepthPageTransformer.
Selama animasi kedalaman, animasi default (slide layar) masih berlangsung, jadi Anda harus menangkal slide layar dengan terjemahan X negatif. Contoh:
Kotlin
view.translationX = -1 * view.width * position
Java
view.setTranslationX(-1 * view.getWidth() * position);
Contoh berikut menunjukkan cara menangkal animasi slide layar default dalam transformator halaman yang berfungsi:
Kotlin
private const val MIN_SCALE = 0.75f @RequiresApi(21) class DepthPageTransformer : ViewPager2.PageTransformer { override fun transformPage(view: View, position: Float) { view.apply { val pageWidth = width when { position < -1 -> { // [-Infinity,-1) // This page is way off-screen to the left. alpha = 0f } position <= 0 -> { // [-1,0] // Use the default slide transition when moving to the left page. alpha = 1f translationX = 0f translationZ = 0f scaleX = 1f scaleY = 1f } position <= 1 -> { // (0,1] // Fade the page out. alpha = 1 - position // Counteract the default slide transition. translationX = pageWidth * -position // Move it behind the left page. translationZ = -1f // Scale the page down (between MIN_SCALE and 1). val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position))) scaleX = scaleFactor scaleY = scaleFactor } else -> { // (1,+Infinity] // This page is way off-screen to the right. alpha = 0f } } } } }
Java
@RequiresApi(21) public class DepthPageTransformer implements ViewPager2.PageTransformer { private static final float MIN_SCALE = 0.75f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0f); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page. view.setAlpha(1f); view.setTranslationX(0f); view.setTranslationZ(0f); view.setScaleX(1f); view.setScaleY(1f); } else if (position <= 1) { // (0,1] // Fade the page out. view.setAlpha(1 - position); // Counteract the default slide transition. view.setTranslationX(pageWidth * -position); // Move it behind the left page view.setTranslationZ(-1f); // Scale the page down (between MIN_SCALE and 1). float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0f); } } }
Referensi lainnya
Untuk mempelajari ViewPager2 lebih lanjut, baca referensi tambahan berikut ini.
Video
- Turning the Page: Migrating to ViewPager2 (Android Dev Summit '19)