ViewPager2 是 ViewPager 庫的改進版本,可提供增強型功能並解決使用 ViewPager 時遇到的一些問題
ViewPager有兩個弊端:1.不能關閉預載入;2.更新adapter不生效
我們在載入資料的時候,viewpager預設會幫我們預載入前後兩個頁面的資料,並且這2個view是不可見的。而目前ViewPager2對Fragment支援只能用FragmentStateAdapter,FragmentStateAdapter在遇到預載入時,只會建立Fragment物件,不會把Fragment真正的加入到佈局中,所以自帶懶載入效果
(1)垂直方向支援,可以通過設定 ViewPager2 元素的 android:orientation 屬性為其啟用垂直分頁
(2)從右到左支援,系統會根據語言區域在適當的情況下自動啟用 RTL 分頁,也可以通過設定 ViewPager2 元素的 android:layoutDirection 屬性為其手動啟用 RTL 分頁
(3)更高效的notifyDataSetChanged,在執行時動態修改 Fragment 集合,而 ViewPager2 會正確顯示修改後的集合
(1)匯入依賴:
implementation "com.google.android.material:material:1.2.1"
(2)activity_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"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabIndicatorColor="@android:color/holo_blue_light"
app:tabIndicatorHeight="2dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@android:color/holo_blue_light"
app:tabTextColor="@android:color/black" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
(3)MainActivity
class MainActivity : AppCompatActivity() {
private var fragmentList: MutableList<Fragment>? = null
private val title = arrayOf("海賊王", "火影忍者", "七龍珠")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
}
private fun init() {
fragmentList = ArrayList()
fragmentList!!.add(OneFragment())
fragmentList!!.add(TwoFragment())
fragmentList!!.add(ThreeFragment())
viewPager.adapter = MyFragmentStateAdapter(this, fragmentList!!)
viewPager.setPageTransformer(ZoomOutPageTransformer())//設定頁面切換的動畫
//TabLayout與ViewPager2聯動
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = title[position]
}.attach()
}
}
可以設定viewPager.isUserInputEnabled = false禁用頁面滑動
TabLayout可以設定app:tabIndicatorFullWidth=「false」,使其下劃線的寬度隨著字的寬改變而改變
(4)MyFragmentStateAdapter
class MyFragmentStateAdapter(fragmentActivity: FragmentActivity, private val list: List<Fragment>) :
FragmentStateAdapter(fragmentActivity) {
override fun createFragment(position: Int): Fragment {
return list[position]
}
override fun getItemCount(): Int {
return list.size
}
}
(5)Fragment切換的動畫
private const val MIN_SCALE = 0.85f
private const val MIN_ALPHA = 0.5f
class ZoomOutPageTransformer : ViewPager2.PageTransformer {
override fun transformPage(view: View, position: Float) {
view.apply {
val pageWidth = width
val pageHeight = height
when {
position < -1 -> {
alpha = 0f
}
position <= 1 -> {
val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position))
val vertMargin = pageHeight * (1 - scaleFactor) / 2
val horzMargin = pageWidth * (1 - scaleFactor) / 2
translationX = if (position < 0) {
horzMargin - vertMargin / 2
} else {
horzMargin + vertMargin / 2
}
scaleX = scaleFactor
scaleY = scaleFactor
alpha = (MIN_ALPHA +
(((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)))
}
else -> {
alpha = 0f
}
}
}
}
}
如果你想實現底部導航欄,用法也差不多
修改佈局檔案
<?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"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabIndicatorColor="@android:color/holo_blue_light"
app:tabIndicatorHeight="2dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@android:color/holo_blue_light"
app:tabTextColor="@android:color/black" />
</LinearLayout>
修改Activity的程式碼
class BottomActivity : AppCompatActivity() {
private var fragmentList: MutableList<Fragment>? = null
private val title = arrayOf("首頁", "位置", "我的")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_bottom)
init()
}
private fun init() {
fragmentList = ArrayList()
fragmentList!!.add(OneFragment())
fragmentList!!.add(TwoFragment())
fragmentList!!.add(ThreeFragment())
//設定底部導航圖示
val icon = arrayListOf(
ContextCompat.getDrawable(this, R.drawable.home_grey)!!,
ContextCompat.getDrawable(this, R.drawable.add_grey)!!,
ContextCompat.getDrawable(this, R.drawable.me_grey)!!
)
val iconSelected = arrayListOf(
ContextCompat.getDrawable(this, R.drawable.home_blue)!!,
ContextCompat.getDrawable(this, R.drawable.add_blue)!!,
ContextCompat.getDrawable(this, R.drawable.me_blue)!!
)
view_pager.adapter = MyFragmentStateAdapter(this, fragmentList!!)
view_pager.setPageTransformer(ZoomOutPageTransformer())
tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
tab!!.icon = iconSelected[tab.position]
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
tab!!.icon = icon[tab.position]
}
override fun onTabReselected(tab: TabLayout.Tab?) {
}
})
view_pager.isUserInputEnabled = false //禁用頁面滑動
//TabLayout與ViewPager2聯動
TabLayoutMediator(tab_layout, view_pager) { tab, position ->
tab.text = title[position]
tab.icon = icon[position]
}.attach()
}
}