Membuat tampilan geser dengan tab menggunakan ViewPager2

Tampilan geser memungkinkan Anda berpindah antara layar yang seinduk, seperti tab, dengan gestur jari horizontal, atau geser. Pola navigasi ini juga disebut sebagai penentuan halaman horizontal.

Topik ini menunjukkan cara membuat tata letak tab dengan tampilan geser untuk beralih antartab, serta cara menampilkan strip judul, bukan tab.

Menerapkan tampilan geser

Anda dapat membuat tampilan geser menggunakan widget ViewPager2 AndroidX. Untuk menggunakan ViewPager2 dan tab, Anda perlu menambahkan dependensi pada ViewPager2 dan Komponen Material ke project.

Untuk menyiapkan tata letak dengan ViewPager2, tambahkan elemen <ViewPager2> ke tata letak XML Anda. Misalnya, jika setiap halaman di tampilan geser menggunakan seluruh tata letak, tata letak Anda akan terlihat seperti ini:

<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" />

Untuk menyisipkan tampilan turunan yang mewakili setiap halaman, tarik tata letak ini ke FragmentStateAdapter. Berikut cara menggunakannya untuk menggeser kumpulan objek Fragment:

Kotlin

class CollectionDemoFragment : Fragment() {
    // When requested, this adapter returns a DemoObjectFragment,
    // representing an object in the collection.
    private lateinit var demoCollectionAdapter: DemoCollectionAdapter
    private lateinit var viewPager: ViewPager2

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.collection_demo, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        demoCollectionAdapter = DemoCollectionAdapter(this)
        viewPager = view.findViewById(R.id.pager)
        viewPager.adapter = demoCollectionAdapter
    }
}

class DemoCollectionAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

    override fun getItemCount(): Int = 100

    override fun createFragment(position: Int): Fragment {
        // Return a NEW fragment instance in createFragment(int).
        val fragment = DemoObjectFragment()
        fragment.arguments = Bundle().apply {
            // The object is just an integer.
            putInt(ARG_OBJECT, position + 1)
        }
        return fragment
    }
}

private const val ARG_OBJECT = "object"

// Instances of this class are fragments representing a single
// object in the collection.
class DemoObjectFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.fragment_collection_object, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        arguments?.takeIf { it.containsKey(ARG_OBJECT) }?.apply {
            val textView: TextView = view.findViewById(android.R.id.text1)
            textView.text = getInt(ARG_OBJECT).toString()
        }
    }
}

Java

public class CollectionDemoFragment extends Fragment {
    // When requested, this adapter returns a DemoObjectFragment,
    // representing an object in the collection.
    DemoCollectionAdapter demoCollectionAdapter;
    ViewPager2 viewPager;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.collection_demo, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        demoCollectionAdapter = new DemoCollectionAdapter(this);
        viewPager = view.findViewById(R.id.pager);
        viewPager.setAdapter(demoCollectionAdapter);
    }
}

public class DemoCollectionAdapter extends FragmentStateAdapter {
    public DemoCollectionAdapter(Fragment fragment) {
        super(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        // Return a NEW fragment instance in createFragment(int).
        Fragment fragment = new DemoObjectFragment();
        Bundle args = new Bundle();
        // The object is just an integer.
        args.putInt(DemoObjectFragment.ARG_OBJECT, position + 1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getItemCount() {
        return 100;
    }
}

// Instances of this class are fragments representing a single
// object in the collection.
public class DemoObjectFragment extends Fragment {
    public static final String ARG_OBJECT = "object";

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_collection_object, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        Bundle args = getArguments();
        ((TextView) view.findViewById(android.R.id.text1))
                .setText(Integer.toString(args.getInt(ARG_OBJECT)));
    }
}

Bagian berikut menunjukkan cara menambahkan tab untuk memudahkan navigasi antar-halaman.

Menambahkan tab menggunakan TabLayout

TabLayout memberikan cara untuk menampilkan tab secara horizontal. Jika digunakan bersama dengan ViewPager2, TabLayout dapat memberikan antarmuka yang umum untuk melakukan navigasi antarhalaman dalam tampilan geser.

Gambar yang menunjukkan TabLayout dengan empat tab, dan tab ketiga dipilih.
Gambar 1. TabLayout dengan empat tab.

Untuk menyertakan TabLayout dalam ViewPager2, tambahkan elemen <TabLayout> di atas elemen <ViewPager2>:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

Selanjutnya, buat TabLayoutMediator untuk menautkan TabLayout ke ViewPager2 dan melampirkannya, sebagai berikut:

Kotlin

class CollectionDemoFragment : Fragment() {
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val tabLayout = view.findViewById(R.id.tab_layout)
        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = "OBJECT ${(position + 1)}"
        }.attach()
    }
    ...
}

Java

public class CollectionDemoFragment extends Fragment {
    ...
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        TabLayout tabLayout = view.findViewById(R.id.tab_layout);
        new TabLayoutMediator(tabLayout, viewPager,
                (tab, position) -> tab.setText("OBJECT " + (position + 1))
        ).attach();
    }
    ...
}

Untuk panduan desain tata letak tab tambahan, lihat dokumentasi Desain Material untuk tab.

Referensi lainnya

Untuk mempelajari ViewPager2 lebih lanjut, baca referensi tambahan berikut ini.

Contoh

Video