Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
📋 Screens, Lists और Navigation  ·  Lesson 28

TabLayout और ViewPager2

Swipe होने वाले tabs

TabLayout tab titles बनाता है। ViewPager2 pages रखता है और user को swipe करने देता है। TabLayoutMediator दोनों को sync रखता है।

9:41▮▮ 85%☰Student Diary⋮AllPendingDoneMaths homeworkHighBuy notebookDone9:41▮▮ 85%☰Student Diary⋮AllPendingDoneMaths homeworkHighPhysics revisionMedium
बाईं ओर swipe → Pending tab select
TabLayouttitlesTabLayoutMediatorsyncViewPager2pagesFragmentStateAdapterfragments बनाता
चार हिस्से

Step 1: Layout

XML – res/layout/fragment_notes.xml
<?xml version="1.0" encoding="utf-8"?>
<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/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

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

Step 2: FragmentStateAdapter

Kotlin
class CoursePagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
    override fun getItemCount() = 3
    override fun createFragment(position: Int): Fragment = when (position) {
        0 -> SyllabusFragment()
        1 -> ReviewsFragment()
        else -> FaqFragment()
    }
}

Step 3: TabLayoutMediator

Kotlin
val titles = listOf("Syllabus", "Reviews", "FAQ")
binding.viewPager.adapter = CoursePagerAdapter(this)
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
    tab.text = titles[position]
}.attach()

// listen for page changes
binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        Log.d("Tabs", "Now on ${titles[position]}")
    }
})

असली code: Student Diary tabs

एक ही NoteListFragment class तीनों tabs के लिए अलग filter argument के साथ reuse होती है:

Kotlin – ui/notes/NotesFragment.kt
package com.codingeasily.studentdiary.ui.notes

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.codingeasily.studentdiary.R
import com.codingeasily.studentdiary.databinding.FragmentNotesBinding
import com.codingeasily.studentdiary.ui.NoteFilter
import com.codingeasily.studentdiary.ui.NoteViewModel
import com.google.android.material.tabs.TabLayoutMediator

/** Home screen: 3 tabs (All / Pending / Done) in a ViewPager2 + a search box in the toolbar. */
class NotesFragment : Fragment() {

    private var _binding: FragmentNotesBinding? = null
    private val binding get() = _binding!!
    private val viewModel: NoteViewModel by activityViewModels()

    private val tabs = listOf(
        NoteFilter.ALL to R.string.tab_all,
        NoteFilter.PENDING to R.string.tab_pending,
        NoteFilter.DONE to R.string.tab_done
    )

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentNotesBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.viewPager.adapter = object : FragmentStateAdapter(this) {
            override fun getItemCount() = tabs.size
            override fun createFragment(position: Int) = NoteListFragment.newInstance(tabs[position].first)
        }
        TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
            tab.setText(tabs[position].second)
        }.attach()

        // Toolbar menu that belongs to this screen only
        requireActivity().addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(R.menu.menu_notes, menu)
                val searchView = menu.findItem(R.id.action_search).actionView as SearchView
                searchView.queryHint = getString(R.string.search_hint)
                searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
                    override fun onQueryTextSubmit(query: String?) = true
                    override fun onQueryTextChange(newText: String?): Boolean {
                        viewModel.setSearchQuery(newText.orEmpty())
                        return true
                    }
                })
            }
            override fun onMenuItemSelected(menuItem: MenuItem) = false
        }, viewLifecycleOwner, Lifecycle.State.RESUMED)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        viewModel.setSearchQuery("")
        _binding = null
    }
}

Icons, badges और modes

Kotlin
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
    tab.text = titles[position]
    tab.setIcon(icons[position])                 // R.drawable.ic_…
}.attach()

binding.tabLayout.getTabAt(1)?.orCreateBadge?.number = 12   // "Reviews 12"
XML – scroll होने वाले कई tabs
<com.google.android.material.tabs.TabLayout
    android:id="@+id/tabLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:tabMode="scrollable"
    app:tabGravity="start" />

Views के साथ onboarding slider

ViewPager2 normal RecyclerView adapter भी लेता है — welcome slides के लिए perfect।

Kotlin
data class Slide(val emoji: String, val title: String, val text: String)

class SlideAdapter(private val slides: List<Slide>) : RecyclerView.Adapter<SlideAdapter.VH>() {
    class VH(val b: ItemSlideBinding) : RecyclerView.ViewHolder(b.root)
    override fun onCreateViewHolder(p: ViewGroup, t: Int) =
        VH(ItemSlideBinding.inflate(LayoutInflater.from(p.context), p, false))   // item root: match_parent
    override fun onBindViewHolder(h: VH, i: Int) {
        h.b.tvEmoji.text = slides[i].emoji
        h.b.tvTitle.text = slides[i].title
        h.b.tvText.text = slides[i].text
    }
    override fun getItemCount() = slides.size
}

// Activity
val slides = listOf(
    Slide("📝", "Write notes", "Homework, revision and exam notes in one place"),
    Slide("⏰", "Never forget", "Get a reminder before every deadline"),
    Slide("📊", "Track progress", "See how much you have completed")
)
binding.pager.adapter = SlideAdapter(slides)
TabLayoutMediator(binding.dots, binding.pager) { _, _ -> }.attach()   // TabLayout as dots
binding.btnNext.setOnClickListener {
    if (binding.pager.currentItem < slides.lastIndex) binding.pager.currentItem++ else finishOnboarding()
}
9:41▮▮ 85%📝Write notesHomework, revision and examnotes●○○NEXT9:41▮▮ 85%⏰Never forgetA reminder before every deadline○●○NEXT
Onboarding: ViewPager2 + TabLayout dots

आम गलतियाँ

  • Mediator पर .attach() भूलना → tabs पर titles नहीं दिखते।
  • ViewPager2 page layouts में wrap_content → crash "Pages must fill the whole ViewPager2"; match_parent use करें।
  • Page fragments के references list में रखना → वे दोबारा बनते हैं; shared ViewModel से बात करें।

सारांश

  • TabLayout + ViewPager2 + FragmentStateAdapter + TabLayoutMediator।
  • मिलते-जुलते tabs के लिए arguments के साथ एक fragment class reuse करें।
  • Sliders और onboarding के लिए RecyclerView adapter वाला ViewPager2।
✅ Practice

तीन tabs (Syllabus, Reviews, FAQ) वाली Course screen बनाइए और review count का badge दिखाइए। 3-slide onboarding screen जोड़िए जो सिर्फ़ पहली बार खुले (SharedPreferences में flag save करें)।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

ViewPager या ViewPager2?
ViewPager2 use करें। यह RecyclerView पर बना है, right-to-left, vertical paging और DiffUtil support करता है, और यही maintained version है।
Fragment के अंदर FragmentStateAdapter को this दें या requireActivity()?
this (parent fragment) दें। तब pages child fragments बनते हैं और parent के साथ साफ़ होते हैं।
Code से कोई खास tab कैसे खोलें?
viewPager.setCurrentItem(index, true) call करें। Mediator की वजह से TabLayout अपने आप follow करता है।
← Android Tutorial (Kotlin)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicSharedPreferences और DataStore आपकी प्रगति: 28 / 43 (65%) · Lesson 29 / 43 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें