美文网首页
navigation+viewpager2简单使用

navigation+viewpager2简单使用

作者: 梧叶已秋声 | 来源:发表于2022-11-12 18:06 被阅读0次

    最后效果图如下:


    image.png

    添加gradle。

        // viewpager2
        implementation 'androidx.viewpager2:viewpager2:1.0.0'
    
        // navigation
        implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
        implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
    
    

    新增navigation.xml。

    <?xml version="1.0" encoding="utf-8"?>
    <navigation 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:id="@+id/navigation.xml"
        app:startDestination="@id/homeFragment">
    
        <fragment
            android:id="@+id/homeFragment"
            android:name="com.example.viewpager2.fragment.home.HomeFragment"
            android:label="fragment_home"
            tools:layout="@layout/fragment_home" />
        <fragment
            android:id="@+id/userFragment"
            android:name="com.example.viewpager2.fragment.user.UserFragment"
            android:label="UserFragment" />
    
    </navigation>
    

    新增bottom_nav.xml。

    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <item
            android:id="@+id/homeFragment"
            android:icon="@drawable/nav_home"
            android:title="@string/tab_home" />
    
        <item
            android:id="@+id/userFragment"
            android:icon="@drawable/nav_user"
            android:title="@string/tab_user" />
    
    </menu>
    

    MainActivity 中初始化navigation。

    class MainActivity : AppCompatActivity() {
        private val binding by lazy {
            ActivityMainBinding.inflate(layoutInflater)
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(binding.root)
            initNavigation()
        }
    
        private fun initNavigation() {
            val host: NavHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
            val navController = host.navController
    
            // 移除 长按 toast
            binding.navigationView.menu.forEach {
                val menuItemView = findViewById<BottomNavigationItemView>(it.itemId)
                menuItemView.setOnLongClickListener(View.OnLongClickListener {
                    return@OnLongClickListener true
                })
            }
            // BottomNavigationView 设置 navController
            binding.navigationView.setupWithNavController(navController)
    
        }
    }
    

    新建ViewPagerAdapter。

    class ViewPagerAdapter(
        private val fragmentStringList: MutableList<String>,
        fm: FragmentManager,
        lifecycle: Lifecycle
    ) : FragmentStateAdapter(fm, lifecycle) {
    
        override fun getItemCount(): Int {
            return fragmentStringList.size
        }
    
        override fun createFragment(position: Int): Fragment {
            return when (fragmentStringList[position]) {
                "FirstFragment" -> FirstFragment.newInstance("","")
                "SecondFragment" -> SecondFragment.newInstance("","")
                else -> ThirdFragment.newInstance("","")
            }
        }
    }
    

    使用adapter

    class HomeFragment : Fragment() {
        private var _binding: FragmentHomeBinding? = null
        private val binding get() = _binding!!
    
        private var mLayoutMediator: TabLayoutMediator? = null
    
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.d(TAG,"inner onCreate")
    
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
           // return inflater.inflate(R.layout.fragment_home, container, false)
            _binding = FragmentHomeBinding.inflate(inflater, container, false)
            Log.d(TAG,"inner onCreateView")
    
            val fragmentStringList = arrayListOf<String>(
                "FirstFragment",
                "SecondFragment",
                "ThirdFragment"
            )
    
    // https://issuetracker.google.com/issues/154751401
    // 解决 使用 navigation + viewPager2 + recyclerview 界面切换时内存泄漏问题 注意点:
    // 1.使用viewLifecycleOwner.lifecycle 而不是 lifecycle
    // 2. recyclerview的adapter 在onDestroyView 中置 null
            val adapter = ViewPagerAdapter(
                fragmentStringList,
                /*requireActivity().supportFragmentManager*/
                childFragmentManager,
                //lifecycle
                viewLifecycleOwner.lifecycle
            )
    
            binding.viewPager2.adapter = adapter
            // 设置 offscreenPageLimit
            binding.viewPager2.offscreenPageLimit = fragmentStringList.size -1
            //绑定 tabLayout 和viewPager
            mLayoutMediator =  TabLayoutMediator(
                binding.tabLayout,
                binding.viewPager2
            ) { tab, position ->
                when (position) {
                    0 -> tab.text = "First"
                    1 -> tab.text = "Second"
                    else -> tab.text = "Third"
                }
            }
            mLayoutMediator?.attach()
    
            return binding.root
        }
    
        override fun onDestroyView() {
            Log.d(TAG,"inner onDestroyView")
            super.onDestroyView()
            // https://stackoverflow.com/questions/61779776/leak-canary-detects-memory-leaks-for-tablayout-with-viewpager2
            // TabLayout 解绑
            mLayoutMediator?.detach()
            mLayoutMediator = null
            binding.viewPager2.adapter = null
            _binding = null
        }
    
    }
    

    本文代码地址:
    https://github.com/VIVILL/SimpleDemo/tree/main/ViewPager2

    参考链接:
    关于ViewPager2内存泄露问题
    FragmentStatePagerAdapter使用不当引起的内存泄漏问题

    相关文章

      网友评论

          本文标题:navigation+viewpager2简单使用

          本文链接:https://www.haomeiwen.com/subject/ogfkxdtx.html