1. 在 Android 项目中引用 JitPack 库
AGP 8.+ 根目录的 settings.gradle
dependencyResolutionManagement {...repositories {...maven { url 'https://jitpack.io' }}
}
AGP 8.+ 根目录如果是 settings.gradle.kts 文件
dependencyResolutionManagement {...repositories {...maven { url = uri("https://jitpack.io") }}
}
AGP 8.- 根目录的 build.gradle
allprojects {repositories {...maven { url 'https://jitpack.io' }}
}
2. 添加依赖
在APP目录中的 build.gradle
implementation("com.github.angcyo.DslTablayout:TabLayout:3.5.3")
implementation("com.github.angcyo.DslTablayout:ViewPager2Delegate:3.5.3")
3. 布局 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=".dsltablayout.BottomNavActivity"><androidx.viewpager2.widget.ViewPager2android:id="@+id/view_pager"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#D5D6D6"/><!-- app:tab_default_index="0" 默认选中第 0 个 tab,默认选中的索引值--><!-- app:tab_item_is_equ_width="true" 让所有的 tab 平分宽度,Item等宽--><!-- app:tab_select_color="#DD0000" 选中当前 tab 时,tab 里文本的颜色 --><!-- app:tab_text_view_id="@id/content" 要放入的 TextView 的 id, 为 tab_item.xml 里的 id 为 content 的TextView --><com.angcyo.tablayout.DslTabLayoutandroid:id="@+id/dsl_tab_layout"android:layout_width="match_parent"android:layout_height="50dp"app:tab_default_index="0"app:tab_convex_background="@color/white"app:tab_item_is_equ_width="true"app:tab_select_color="#DD0000"app:tab_text_view_id="@id/content"/>
</LinearLayout>
4. 底部 tab_item.xml 布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:gravity="center"><ImageViewandroid:id="@+id/icon"android:layout_width="23dp"android:layout_height="23dp"android:src="@drawable/selector_tab_video"/><TextViewandroid:id="@+id/content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="12sp"android:text="发现"/></LinearLayout>
5. 每个底部 tab 对应的 fragment
a. DiscoveryFragment
class DiscoveryFragment : Fragment() {override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_discovery, container, false)}companion object {fun newInstance(): DiscoveryFragment{val args = Bundle()val fragment = DiscoveryFragment()fragment.arguments = argsreturn fragment}}
}
b. fragment_discovery.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".fragment.DiscoveryFragment"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="25sp"android:text="发现界面"android:layout_gravity="center"/></FrameLayout>
其它三个 Fragment(VideoFragment,CategoryFragment,MeFragment)类似。
6. Adapter
class BottomTabAdapter(fragmentActivity : FragmentActivity, private val count : Int): FragmentStateAdapter(fragmentActivity) {override fun getItemCount(): Int {return count}/*** position 是每个 Fragment 对应的下标*/override fun createFragment(position: Int): Fragment {return when(position){0 -> DiscoveryFragment.newInstance()1 -> VideoFragment.newInstance()2 -> CategoryFragment.newInstance()else -> MeFragment.newInstance()}}
}
7. MainActivity.kt。填充Fragment 和 TabLayout,实现底部导航
在APP目录中的 build.gradle 的 android 下添加 ViewBinding 的使用
android {...viewBinding{enable=true}
}
class MainActivity : AppCompatActivity() {private lateinit var binding : ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// TODO 1初始化底部按钮(tab_item)并添加到 dslTabLayoutfor (i in bottomItemTitle.indices){//TODO TabItemBinding.inflate(layoutInflater)) 通过 ViewBinding 的方式,拿到 tab_item.xml 布局TabItemBinding.inflate(layoutInflater).apply {content.text = bottomItemTitle[i]icon.setImageResource(bottomItemIcon[i])// 将当前添加了 icon 和 content 的 tab_item 添加到 TabLayout 中binding.dslTabLayout.addView(root)}}// TODO 2ViewPager + Fragmentbinding.viewPager.offscreenPageLimit = bottomItemTitle.sizebinding.viewPager.adapter = BottomTabAdapter(this, bottomItemTitle.size)// TODO 3将 ViewPager 中的 Fragment 与 底部的 Tab 绑定ViewPager2Delegate.install(binding.viewPager, binding.dslTabLayout, false)}companion object{// TODO 底部 item 的标题private val bottomItemTitle = listOf("发现","视频","分类","我的")// TODO 底部 item 的图标private val bottomItemIcon = listOf(R.drawable.selector_tab_discovery,R.drawable.selector_tab_video,R.drawable.selector_tab_category,R.drawable.selector_tab_me)}
}
完整项目
链接 DslTabLayout+ViewPager2+Fragment 实现底部导航栏
提取码:ei9o
如果向想通过Android原生的 BottomNavigationView+Viewpager2+Fragment 实现底部导航栏,可以看这一篇帖子 Android---简易的底部导航栏
DslDslTabLayout 官网 : https://github.com/angcyo/DslTabLayout