Search code examples
androidkotlinandroid-viewpagerandroid-architecture-navigationbottom-navigation-bar

How make ViewPager work with Bottom Navigation tab in kotlin project


I have some issue in order to make ViewPager work as nested navigation part with Bottom Navigation Tab in android Kotlin

this is my code :

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var viewPager : ViewPager2
    lateinit var viewPageAdpater : ViewPagerAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewPager = findViewById(R.id.viewPager)
        viewPageAdpater = ViewPagerAdapter(this)
        viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
        viewPager.adapter = viewPageAdpater




    }


}

activite_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">


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

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/bottom_navigation_menu"
        android:background="?android:attr/windowBackground"/>


</LinearLayout>

my bottom_tab_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/nav_viewpager"
        android:title="Home"
        android:icon="@drawable/ic_launcher_foreground" />
    <item
        android:id="@+id/nav_items_discover"
        android:title="item List"
        android:icon="@drawable/ic_launcher_foreground" />
    <item
        android:id="@+id/nav_user"
        android:title="User"
        android:icon="@drawable/ic_launcher_foreground" />
</menu>

my ViewpagerAdapter.kt

class ViewPagerAdapter(mainActivity: MainActivity) : FragmentStateAdapter(mainActivity) {

    override fun getItemCount(): Int {
        return 5
    }

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            0 -> Home_Main()
            1 -> Home_Itemslist()
            2 -> Home_Contactus()

            else -> Home_Main()
        }
    }
}

what i want achieve is :

  1. bottom tab navigation - home (contains 3 subs FRAGMENTS in Viewpager)
  2. bottom tab navigation - item_discover (independent Fragment)
  3. bottom tab navigation - user login (another activate)

Solution

  • I have same problem and then I try below code for application, it's work for me. I am writing down code here please check if it's help you.

    Thank you

    MainActivity.kt

    class MainActivity : AppCompatActivity() {
    
    lateinit var viewPager: ViewPager2
    lateinit var viewPageAdapter: ViewPagerAdapter
    lateinit var bottomNavigationView: BottomNavigationView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        viewPager = findViewById(R.id.viewPager)
        bottomNavigationView = findViewById(R.id.bottomNavigationView)
    
        viewPageAdapter = ViewPagerAdapter(this)
        viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
        viewPager.adapter = viewPageAdapter
    
        // Handle BottomNavigationView item selection
        bottomNavigationView.setOnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.nav_viewpager -> {
                    viewPager.currentItem = 0 // This will handle the Home fragment with nested ViewPager
                    true
                }
                R.id.nav_items_discover -> {
                    viewPager.currentItem = 1 // This will handle the item discover fragment
                    true
                }
                R.id.nav_user -> {
                    // Navigate to User Login Activity
                    val intent = Intent(this, UserLoginActivity::class.java)
                    startActivity(intent)
                    true
                }
                else -> false
            }
        }
    
        // Sync ViewPager with BottomNavigationView
        viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageSelected(position: Int) {
                bottomNavigationView.menu.getItem(position).isChecked = true
            }
        })
    }
    

    Update ViewPagerAdapter

    class ViewPagerAdapter(mainActivity: MainActivity) : FragmentStateAdapter(mainActivity) {
    
        override fun getItemCount(): Int {
            return 3 // Number of main tabs
        }
    
        override fun createFragment(position: Int): Fragment {
            return when (position) {
                0 -> HomeFragment() // Home with ViewPager of nested fragments
                1 -> ItemDiscoverFragment() // Independent fragment for item discovery
                else -> HomeFragment()
            }
        }
    }
    

    HomeFragment.kt

    class HomeFragment : Fragment() {
    
        lateinit var nestedViewPager: ViewPager2
        lateinit var nestedAdapter: NestedViewPagerAdapter
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val view = inflater.inflate(R.layout.fragment_home, container, false)
            nestedViewPager = view.findViewById(R.id.nestedViewPager)
    
            nestedAdapter = NestedViewPagerAdapter(this)
            nestedViewPager.adapter = nestedAdapter
    
            return view
        }
    }
    

    NestedViewPagerAdapter

    class NestedViewPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
    
        override fun getItemCount(): Int {
            return 3 // Number of sub-fragments in Home
        }
    
        override fun createFragment(position: Int): Fragment {
            return when (position) {
                0 -> Home_Main()
                1 -> Home_Itemslist()
                2 -> Home_Contactus()
                else -> Home_Main()
            }
        }
    }
    

    fragment_home.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.viewpager2.widget.ViewPager2 xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/nestedViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />