{i>Slide<i} layar adalah transisi dari satu seluruh layar ke layar lainnya dan umum dengan UI seperti
{i>setup wizards<i} dan {i>slideshow<i}. Topik ini menunjukkan cara melakukan {i>slide<i} layar dengan
ViewPager2
. Objek ViewPager2
dapat otomatis menganimasikan geser layar. Berikut ini contohnya
{i>slide<i} layar yang bertransisi dari satu layar konten ke layar konten berikutnya:
Jika Anda ingin langsung melihat contoh yang berfungsi penuh, lihat aplikasi contoh ini di GitHub.
Untuk menggunakan ViewPager2
, Anda perlu menambahkan beberapa
Dependensi AndroidX ke
proyek. 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 mendefinisikan string untuk isi 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
Fragment
yang
mengembalikan tata letak yang Anda buat di
onCreateView()
. Anda bisa membuat instance fragmen ini dalam aktivitas induk kapan pun Anda memerlukan
halaman baru yang akan 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 bertransisi pada halaman, dan
{i>slide<i} menampilkan animasi {i>slide<i} layar secara {i>default<i}, sehingga Anda tidak perlu membuat animasi Anda sendiri.
ViewPager2
penggunaan
FragmentStateAdapter
sebagai pasokan untuk halaman baru yang akan ditampilkan, sehingga FragmentStateAdapter
menggunakan
fragmen yang telah dibuat.
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
FragmentStateAdapter
dan mengimplementasikancreateFragment()
untuk menyediakan instanceScreenSlidePageFragment
sebagai halaman baru. Anda harus menerapkangetItemCount()
untuk adaptor Pager, yang menampilkan jumlah halaman yang dibuat oleh adaptor. Ada lima dalam contoh ini. - Mengaitkan
FragmentStateAdapter
ke 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 geser layar default, implementasikan metode
ViewPager2.PageTransformer
dan menyediakannya ke objek ViewPager2
. Antarmuka tersebut mengekspos satu
,
transformPage()
.
Pada setiap titik dalam transisi layar, metode ini dipanggil satu kali untuk setiap halaman yang terlihat—ada
biasanya hanya satu halaman yang terlihat—dan untuk halaman yang berdekatan dari layar. Misalnya, jika halaman tiga
terlihat dan pengguna menarik ke halaman empat, transformPage()
dipanggil untuk halaman dua,
tiga, dan empat di setiap langkah {i>gesture <i}tersebut.
Dalam implementasi transformPage()
, Anda kemudian dapat membuat slide kustom
animasi dengan menentukan laman mana yang perlu diubah berdasarkan posisi halaman pada
layar. Dapatkan posisi halaman dari parameter position
elemen
Metode transformPage()
.
Parameter position
menunjukkan lokasi halaman tertentu dibandingkan 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 dari sisi kanan layar, nilai posisinya adalah 1
. Jika pengguna men-scroll
setengah dari 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 menyetel properti halaman menggunakan metode seperti
setAlpha()
,
setTranslationX()
,
atau
setScaleY()
.
Ketika Anda memiliki implementasi
PageTransformer
,
panggilan telepon
setPageTransformer()
dengan implementasi Anda untuk menerapkan animasi kustom. Misalnya, jika Anda memiliki
PageTransformer
bernama ZoomOutPageTransformer
, Anda dapat menyetel
animasi 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 Transformer halaman zoom-out dan
Bagian Transformer halaman depth untuk contoh
PageTransformer
.
Transformer halaman zoom-out
Transformer halaman ini menyusutkan dan memudarkan halaman saat scroll di antara halaman yang berdekatan. Sebagai halaman semakin dekat ke tengah, ia tumbuh kembali ke ukuran normal dan memudar.
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
Transformer halaman ini menggunakan animasi {i>slide<i} {i>default<i} untuk menggeser halaman ke kiri, saat menggunakan "kedalaman" animasi untuk menggeser halaman ke kanan. Animasi kedalaman ini memudarkan halaman dan memperkecil skalanya secara linear.
Selama animasi kedalaman, animasi default (geser layar) masih berlangsung, jadi Anda harus menangkal geser layar dengan terjemahan X negatif. Contoh:
Kotlin
view.translationX = -1 * view.width * position
Java
view.setTranslationX(-1 * view.getWidth() * position);
Contoh berikut menunjukkan cara menetralkan animasi geser layar default dalam fungsi transformer halaman:
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.
Contoh
- Contoh ViewPager2 di GitHub.
Video
- Membalikkan Halaman: Bermigrasi ke ViewPager2 (Android Dev Summit '19)