ViewPager + Fragment 实现滑动导航栏。
先上图
image.png
image.png
一、布局文件
使用HorizontalScrollView可以让超出屏幕的导航栏可以滑动,每个RadioButton代表一个导航标题,android:button="@null"去掉RadioButton的选中圆圈
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/viewPager"
android:layout_weight="1"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/horizontalScrollView"
android:scrollbars="none">
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/radioGroup">
<RadioButton
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:drawableTop="@drawable/check_radiobutton"
android:layout_margin="10dp"
android:checked="true"
android:id="@+id/rb_one"/>
<RadioButton
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:layout_margin="10dp"
android:drawableTop="@drawable/check_button2"
android:id="@+id/rb_two"/>
<RadioButton
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:drawableTop="@drawable/check_button3"
android:layout_margin="10dp"
android:id="@+id/rb_three"/>
<RadioButton
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:drawableTop="@drawable/check_button4"
android:layout_margin="10dp"
android:id="@+id/rb_four"/>
</RadioGroup>
</HorizontalScrollView>
选中的下划线xml文件
<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" tools:ignore="MissingDefaultResource">
<item android:state_checked="true">
<layer-list>
<item android:top="25dp" android:height="1dp">
<shape android:shape="rectangle">
<size android:height="1dp"/>
<solid android:color="#ffff"/>
</shape>
</item>
</layer-list>
</item>
</selector>
二、MainActivity
将RadioButton导航栏的标题装在一个list集合里面,新增标题的时候可以直接在list里添加RadioButton的id,简约了ViewPage滑动定位到相应的RadioButton和相应的Fragment,不用when每个id去判断。
var list = arrayListOf<Int>(R.id.rb_one,R.id.rb_two,R.id.rb_three,R.id.rb_four)
增加标题时也要add对应的Fragment
fragments.add(FragmentOne())
fragments.add(FragmentTwo())
fragments.add(FragmentThree())
fragments.add(FragmentFour())
viewPager.offscreenPageLimit = 4 //缓存4个fragment
fragmentManager = supportFragmentManager
viewPager.adapter = MyFragmentAdapter(fragmentManager,fragments)
radioGroup.setOnCheckedChangeListener(this)
viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener{
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
override fun onPageSelected(position: Int) {
radioGroup.check(list[position])
}
})
}
override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
for (i in list.indices){
if (list[i] == checkedId){
viewPager.setCurrentItem(i)
}
scrollToFocus()
}
}
/**
* 定位RadioButton,超过屏幕跟踪滑动
*/
private fun scrollToFocus() {
//获取屏幕宽度
val screenWith = this.resources.displayMetrics.widthPixels
//每个RadioButton的X坐标
val item = findViewById<RadioButton>(radioGroup.checkedRadioButtonId)
var x = item.x.toInt()
if (x + item.width < screenWith){
x = 0
}
horizontalScrollView.smoothScrollTo(x,0)
}
三、自定义MyFragmentAdapter
继承FragmentStatePagerAdapter 。当ViewPager中的Fragment数量相对较多时继承FragmentStatePagerAdapter,少时可以继承FragmentPagerAdapter
class MyFragmentAdapter : FragmentStatePagerAdapter {
private lateinit var fragments: ArrayList<Fragment>
constructor(fragmentManager: FragmentManager, fragments: ArrayList<Fragment>) : super(fragmentManager){
this.fragments = fragments
}
override fun getItem(position: Int): Fragment {
return fragments.get(position)
}
override fun getCount(): Int {
return fragments.size
}
}