一、基本介绍
底部导航栏在Android应用中随处可见,今天使用ViewPager+RadioGroup+Fragment这三个控件来实现此功能。前面写了有三种实现方式,有兴趣可以去看看
二、实现原理
Fragment用于承载和展示内容,Viewpager用于界面的切换,RadioGroup用于展示导航栏和点击事件通知ViewPager切换页面。
三、实现过程
第一步:布局代码,主要控件就是ViewPager和RadioGroup,再往里面放五个RadioButton子项。
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:orientation="vertical"> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/nav_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center" android:padding="4dp" android:text="ViewPager+RadioGroup+Fragment" android:textColor="@color/black" android:textSize="18sp" android:textStyle="bold" /> <androidx.viewpager.widget.ViewPager android:id="@+id/fragment_container_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/nav_radiogroup" android:layout_below="@id/nav_text" /> <View android:layout_width="match_parent" android:layout_height="0.3dp" android:layout_above="@id/nav_radiogroup" android:background="@color/tab_color_false" /> <RadioGroup android:id="@+id/nav_radiogroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@color/white" android:orientation="horizontal"> <RadioButton android:id="@+id/nav_radio_button_1" style="@style/radiobutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/food_avocado" android:text="首页" android:textColor="@drawable/selector_main_rb_text_color" /> <RadioButton android:id="@+id/nav_radio_button_2" style="@style/radiobutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/food_bread" android:text="游戏" android:textColor="@drawable/selector_main_rb_text_color" /> <RadioButton android:id="@+id/nav_radio_button_3" style="@style/radiobutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/food_cake" android:text="学习" android:textColor="@drawable/selector_main_rb_text_color" /> <RadioButton android:id="@+id/nav_radio_button_4" style="@style/radiobutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/food_eggyolkcake" android:text="放松" android:textColor="@drawable/selector_main_rb_text_color" /> <RadioButton android:id="@+id/nav_radio_button_5" style="@style/radiobutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/food_cookie" android:text="我的" android:textColor="@drawable/selector_main_rb_text_color" /> </RadioGroup> </RelativeLayout> </layout> RadioButton的textColor的xml代码:选中为蓝色,未选中为黑色 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/blue" android:state_checked="true"/> <item android:color="@color/black" android:state_checked="false"/> </selector> RadioButton的style属性代码:在style.xml文件里 <style name="radiobutton"> <!--底部导航radiobutton的属性设置--> <item name="android:layout_weight">1</item> <item name="android:layout_width">0dp</item> <item name="android:drawablePadding">4dp</item> <item name="android:layout_height">wrap_content</item> <item name="android:button">@null</item> <item name="android:gravity">center</item> <item name="android:textSize">12sp</item> <item name="android:textColor">@drawable/selector_main_rb_text_color</item> </style> eg: 1.设置weight都为1,这样的话子项的宽度都会是一样的。 2.drawablePadding属性,是为了让图片和文字有一点间距,好看些。 3.button为null,这样就可以去掉radioButton的那个不好看的默认按钮。 第二步:业务逻辑代码 package com.example.lxview.lxhome.func.nav.activity import android.widget.RadioGroup import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.example.lxview.R import com.example.lxview.base.activity.BaseBindActivity import com.example.lxview.base.fragment.BaseFragment import com.example.lxview.databinding.NavViewpagerRadiogroupActivityLayoutBinding import com.example.lxview.home.fragment.* /** * author: 李 祥 * date: 2022/6/28 8:48 下午 * description: */ class NavViewPagerRadioGroupActivity : BaseBindActivity<NavViewpagerRadiogroupActivityLayoutBinding>() { override val layout: Int get() = R.layout.nav_viewpager_radiogroup_activity_layout private lateinit var homeFragment: HomeFragment private lateinit var toolsFragment: ToolsFragment private lateinit var relaxFragment: RelaxFragment private lateinit var viewPager: ViewPager private lateinit var radioGroup: RadioGroup private lateinit var meFragment: MineFragment private lateinit var playFragment: PlayFragment private lateinit var fragments: Array<BaseFragment> private val titles = arrayOf("首页", "视频", "用户", "音乐", "我的") override fun initView() { initFragment() viewPager = mBinding.fragmentContainerViewpager radioGroup = mBinding.navRadiogroup //绑定fragment列表 viewPager.adapter = object : FragmentPagerAdapter(supportFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { override fun getCount(): Int { return fragments.size } override fun getItem(position: Int): Fragment { return fragments[position] } override fun getPageTitle(position: Int): CharSequence { return titles[position] } } } override fun initListener() { radioGroup.setOnCheckedChangeListener { _, checkedId -> when (checkedId) { //点击切换viewpager页面 R.id.nav_radio_button_1 -> { viewPager.currentItem = 0 } R.id.nav_radio_button_2 -> { viewPager.currentItem = 1 } R.id.nav_radio_button_3 -> { viewPager.currentItem = 2 } R.id.nav_radio_button_4 -> { viewPager.currentItem = 3 } R.id.nav_radio_button_5 -> { viewPager.currentItem = 4 } } } viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { } override fun onPageSelected(position: Int) { //当页面左右滑动发生改变时,radiogroup也改变子项的选择状态 when (position) { 0 -> radioGroup.check(R.id.nav_radio_button_1) 1 -> radioGroup.check(R.id.nav_radio_button_2) 2 -> radioGroup.check(R.id.nav_radio_button_3) 3 -> radioGroup.check(R.id.nav_radio_button_4) 4 -> radioGroup.check(R.id.nav_radio_button_5) } } override fun onPageScrollStateChanged(state: Int) { } }) } private fun initFragment() { homeFragment = HomeFragment() toolsFragment = ToolsFragment() relaxFragment = RelaxFragment() meFragment = MineFragment() playFragment = PlayFragment() fragments = arrayOf(homeFragment, toolsFragment, playFragment, relaxFragment, meFragment) } }
关于radioGroup和Viewpager的互相监听切换都写在代码里了,代码也注释了,如果想在点击item或者左右滑动后更改图片,也可以在这两个监听事件里进行更改,也可以直接设置drawableTop的资源文件,改成selector xml文件,比如在drawable先新建一个
drawable_my_selector.xml文件 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/icon_checked_my" android:state_checked="true" /> <item android:drawable="@mipmap/icon_normal_my" android:state_checked="false" /> </selector> 然后在最上边的xml布局文件里将drawableTop属性更改为: android:drawableTop="@drawable/drawable_my_selector" ..... <RadioButton android:id="@+id/nav_radio_button_5" style="@style/radiobutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/drawable_my_selector" android:text="我的" android:textColor="@drawable/selector_main_rb_text_color" /> ......
总结:总的来说,底部导航栏的实现方式有很多种,也很简单,怎样选择可以根据自己的喜好和需求来实现,有时候子项大小不一啊,各种过度动画之类的也会影响自己的选择。关于底部导航栏的文章我就写这四章了,当然并不是只有这些实现方式,也可以有其他的组合方式,或者其他的实现方法。