Search code examples
androidandroid-fragmentsswipeandroid-tablayoutandroid-viewpager2

Android TabLayout not working in Fragment with Fragment


I use the code below to setup my TabLayout inside a Fragment. The problem is that the tabs are not swiping even though I used registerOnPageChangeCallback(). When I add fragment containing tablayout to a bottom navigation view then when swiping the tablayout goes to a white screen with no fragments. What am I doing wrong? If i use tablayout in activity it can be swiped as usual.

public class BookcaseFragment extends Fragment {

    private TabLayout tabLayout;
    private ViewPager2 mViewPager;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_bookcase, container, false);

    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        tabLayout = view.findViewById(R.id.tab_layout_bookcase);
        mViewPager = view.findViewById(R.id.bookcase_viewpager);

        BookcaseViewPagerAdapter adapter = new BookcaseViewPagerAdapter(this);
        mViewPager.setAdapter(adapter);

        new TabLayoutMediator(tabLayout, mViewPager, (tab, position) -> {
            switch (position){
                case 0:
                    tab.setText("following");
                    break;
                case 1:
                    tab.setText("downloaded");
                    break;
                case 2:
                    tab.setText("watched");
                    break;
            }
        }).attach();

        mViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                tabLayout.getTabAt(position).select();
                System.out.println(position);
            }
        });

    }
}
public class BookcaseViewPagerAdapter extends FragmentStateAdapter {


    public BookcaseViewPagerAdapter(@NonNull Fragment fragment) {
        super(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position){
            case 0:
                return new FollowingFragment();
            case 1:
                return new DownloadedFragment();
            case 2:
                return new JustWatchedFragment();
            default:
                return new FollowingFragment();
        }
    }

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

Solution

  • This could be caused by the viewpager being null. Did you make the viewpager in the fragment itself?

    I was able to get it to swipe as long as I put the viewpager inside the fragments xml.

    written in kotlin, sorry, but should still be the same idea.

    class BookcaseFragment : Fragment() {
    
        private var tabLayout: TabLayout? = null
        private var mViewPager: ViewPager2? = null
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_bookcase, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            tabLayout = view.findViewById(R.id.tab_layout_bookcase)
            mViewPager = view.findViewById(R.id.bookcase_pager)
    
            val adapter = BookcaseViewPagerAdapter(this)
            adapter.addFragment(BlankFragment())
            adapter.addFragment(BlankFragment())
            adapter.addFragment(BlankFragment())
            mViewPager?.adapter = adapter
    
            tabLayout?.let { tabs->
                mViewPager?.let { pager->
    
                    TabLayoutMediator(tabs, pager,
                        TabConfigurationStrategy { tab: TabLayout.Tab, position: Int ->
                            when (position) {
                                0 -> tab.text = "following"
                                1 -> tab.text = "downloaded"
                                2 -> tab.text = "watched"
                            }
                        }).attach()
    
                    pager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
                        override fun onPageSelected(position: Int) {
                            super.onPageSelected(position)
                            tabs.getTabAt(position)!!.select()
                            println(position)
                        }
                    })
    
                }
            }
        }
    
    }
    class BookcaseViewPagerAdapter(fragment: Fragment) :
        FragmentStateAdapter(fragment) {
        private val arrayList: ArrayList<Fragment> = ArrayList()
    
        fun getItem(position: Int): Fragment {
            return arrayList[position]
        }
    
        fun addFragment(fragment: Fragment) {
            arrayList.add(fragment)
        }
    
        override fun getItemCount(): Int {
            return arrayList.size
        }
    
        override fun createFragment(position: Int): Fragment {
            return arrayList[position]
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".BookcaseFragment">
    
        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/bookcase_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
        </androidx.viewpager2.widget.ViewPager2>
    
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout_bookcase"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
    
        </com.google.android.material.tabs.TabLayout>
    
    </FrameLayout>
    

    you can find more information in this answer. Proper implementation of ViewPager2 in Android