navigation+viewpager2简单使用
2022-11-12 本文已影响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使用不当引起的内存泄漏问题