码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Android 底部导航栏(三、ViewPager+TabLayout+Fragment)简单易懂


    底部导航栏在Android应用中随处可见,今天使用ViewPager+TabLayout+Fragment这三个控件来实现此功能。

    前面使用了另外两个方法来实现导航栏,不过我还是更喜欢Viewpager,代码也少,毕竟前两个不能左右滑动。

    Android 底部导航栏(一、BottomNavigationView+Menu+Fragment)_&岁月不待人&的博客-CSDN博客_android 底部导航栏现在常用的App主页都会有一个底部导航栏,根据需求也使用过好几种方法进行实现,于是想着还是总结一下,今天还写一个简单的BottomNavigationView方法来实现这个功能它是android原生的一个底部导航框架,一般和Fragment一起使用。xml布局:最外层的layout不用管,那是databinding框架的根布局,主要的布局FrameLayout来装载fragment列表,BottomNavigationView实现底部导航栏,最后监听绑定实现点击切换其中BottomNavigationhttps://blog.csdn.net/LoveFHM/article/details/125498372?spm=1001.2014.3001.5501

    Android 底部导航栏(二、自定义View+Fragment)_&岁月不待人&的博客-CSDN博客总结:我这上面只实现了简单的点击切换,用自定义View来实现底部导航栏,很自由,可以实现一些稀奇古怪的需求,但是很多方法的回调,切换时的动画,就需要自己去实现,可能会相对复杂一些。最后加上Fragment的切换,点击监听等等,坏处的话就是自己写的,可能没有封装好的那么完善,很多方法,状态需要自己去写。上一片文章用的是BottomNavigationView+Menu+Fragment,但是可能有时候需求不一样,menu的样式不太够,所以需要自定义View来实现。https://blog.csdn.net/LoveFHM/article/details/127651226?spm=1001.2014.3001.5501

    一、基本介绍

    ViewPager:Android 3.0后引入的一个UI控件——ViewPager(视图滑动切换工具),Viewpager使用起来就是我们通过创建adapter给它填充多个view,左右滑动时,切换不同的view。Google官方是建议我们使用Fragment来填充ViewPager的,这样 可以更加方便的生成每个Page,以及管理每个Page的生命周期。可以用来主页/模块切换,图片轮播,新手引导等等。

    ViewPager 全面总结_淡然一笑、的博客-CSDN博客_viewpager

    TabLayout:TabLayout提供了一个水平布局用于展示tabs,继承自HorizontalScrollView。TabLayout一般结合ViewPager+Fragment的使用实现滑动的标签选择器。

    Android控件-TabLayout使用介绍_Android开发猿的博客-CSDN博客_tablayout

    Fragment:Fragment可以说是轻量级的Activity,是Android3.0新增的概念。这个就很基础了,不给链接了。

    二、实现原理

    Fragment用于承载和展示内容,Viewpager用于界面的切换,TabLayout用于展示导航栏和点击事件通知ViewPager切换页面。

    三、实现过程

    第一步:先拉界面哦

    1. "1.0" encoding="utf-8"?>
    2. <layout xmlns:app="http://schemas.android.com/apk/res-auto"
    3. xmlns:tools="http://schemas.android.com/tools">
    4. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    5. android:layout_width="match_parent"
    6. android:layout_height="match_parent"
    7. android:background="@color/white"
    8. android:orientation="vertical">
    9. android:id="@+id/nav_text"
    10. android:layout_width="match_parent"
    11. android:layout_height="wrap_content"
    12. android:layout_marginTop="20dp"
    13. android:gravity="center"
    14. android:padding="4dp"
    15. android:text="ViewPager+TabLayout+Fragment"
    16. android:textColor="@color/black"
    17. android:textSize="18sp"
    18. android:textStyle="bold" />
    19. <androidx.viewpager.widget.ViewPager //承载内容
    20. android:id="@+id/fragment_container_viewpager"
    21. android:layout_width="match_parent"
    22. android:layout_height="match_parent"
    23. android:layout_above="@id/nav_tablayout"
    24. android:layout_below="@id/nav_text" />
    25. <View
    26. android:layout_width="match_parent"//只是个分割线
    27. android:layout_height="0.3dp"
    28. android:layout_above="@id/nav_tablayout"
    29. android:background="@color/tab_color_false"/>
    30. <com.google.android.material.tabs.TabLayout
    31. android:id="@+id/nav_tablayout"
    32. android:layout_width="match_parent"
    33. android:layout_height="wrap_content"
    34. android:layout_alignParentBottom="true"
    35. android:background="@color/white"
    36. app:tabBackground="@color/white"
    37. app:tabIndicatorAnimationMode="elastic"
    38. app:tabIndicatorColor="@color/blue"
    39. app:tabIndicatorFullWidth="false"
    40. app:tabIndicatorGravity="bottom"
    41. app:tabMode="fixed"
    42. app:tabRippleColor="@android:color/transparent"
    43. app:tabSelectedTextColor="@color/black"
    44. app:tabTextColor="@color/bar_grey"
    45. tools:layout_height="50dp"
    46. />
    47. RelativeLayout>
    48. layout>

    第二步:业务代码,就是初始化这两个控件,tablayout初始化item,设置属性,使用tabLayout.setupWithViewPager(viewPager)绑定viewpager,然后往Viewpager里面加fragment列表,然后给viewpager设置fragment。(kotlin实现,如果你是java代码,拷进项目它会自动转码为java,布局绑定用的databinding,没用过看核心代码就行了)

    1. class NavViewPagerTabActivity : BaseBindActivity<NavViewpagerTablayoutActivityLayoutBinding>() {
    2. override val layout: Int
    3. get() = R.layout.nav_viewpager_tablayout_activity_layout
    4. private lateinit var homeFragment: HomeFragment
    5. private lateinit var toolsFragment: ToolsFragment
    6. private lateinit var relaxFragment: RelaxFragment
    7. private lateinit var viewPager: ViewPager
    8. private lateinit var tabLayout: TabLayout
    9. private lateinit var meFragment: MineFragment
    10. private lateinit var playFragment: PlayFragment
    11. private lateinit var fragments: Array
    12. private val titles = arrayOf("首页", "视频", "用户")
    13. override fun initView() {
    14. initFragment()//初始化fragment列表
    15. viewPager = mBinding.fragmentContainerViewpager
    16. tabLayout = mBinding.navTablayout
    17. tabLayout.setupWithViewPager(viewPager)//绑定viewpager
    18. // for (element in titles) tabLayout.addTab(tabLayout.newTab().setText(element))
    19. viewPager.adapter = object :FragmentPagerAdapter(supportFragmentManager,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT){
    20. override fun getCount(): Int {
    21. return fragments.size
    22. }
    23. override fun getItem(position: Int): Fragment {
    24. return fragments[position]
    25. }
    26. override fun getPageTitle(position: Int): CharSequence {
    27. return titles[position]
    28. }
    29. }
    30. }
    31. private fun initFragment() {
    32. homeFragment = HomeFragment()
    33. toolsFragment = ToolsFragment()
    34. relaxFragment = RelaxFragment()
    35. meFragment = MineFragment()
    36. playFragment = PlayFragment()
    37. // fragments = arrayOf(homeFragment, toolsFragment, playFragment, relaxFragment, meFragment)
    38. fragments = arrayOf(homeFragment, toolsFragment, meFragment)
    39. }
    40. }

    eg:可以看到我把上面的这行代码注释,但是运行出来,tab是添加上了,为什么呢?

    // for (element in titles) tabLayout.addTab(tabLayout.newTab())

    原因很简单,是在tabLayout.setupWithViewPager的时候,TabLayout中先将所有tabs remove了,然后取的PagerAdapter中的getPageTitle返回值添加的tab。就是在给ViewPager设置Adapter的时候,一定要重写getPageTitle(int position)方法,不然TabLayout中的标签是看不到的,即使在addTab时newTab().setText(tabs[i])也没用。

    这样就简单的实现了导航栏!可以单独为viewpager和tablayout添加监听事件,并且绑定也只需要一行代码,可以实现左右滑动切换界面,当然,如果想禁止左右滑的触摸事件也可以对viewpager事件作拦截。关于viewpager和tablayout,他们还有很多属性可以去配置,如果想详细了解的可以去看上面的两个链接去学习一下!

    实现效果:

     

    进阶知识点一:

    为tablayout添加监听事件:

    1. tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
    2. override fun onTabSelected(tab: TabLayout.Tab?) {
    3. TODO("Not yet implemented")
    4. }
    5. override fun onTabUnselected(tab: TabLayout.Tab?) {
    6. TODO("Not yet implemented")
    7. }
    8. override fun onTabReselected(tab: TabLayout.Tab?) {
    9. TODO("Not yet implemented")
    10. }
    11. })

     为ViewPager添加监听事件:

    1. viewPager?.setOnPageChangeListener(object : ViewPager.OnPageChangeListener {
    2. override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
    3. }
    4. override fun onPageSelected(position: Int) {
    5. }
    6. override fun onPageScrollStateChanged(state: Int) {
    7. }
    8. })

    进阶知识点二:

    为TabLayout设置自定义View,有时候底部导航栏可能不只是文字,他可能是图片和文字混合,可能点击后有图片,文字的大小变化,那么就需要为其单独配置view,并在监听事件里重新绘制界面。

    这儿我展示一份项目里的代码:

    1. override fun onTabSelected(tab: TabLayout.Tab) {
    2. viewPager?.currentItem = tab.position
    3. val customView = tab.customView
    4. if (tab.position == 0) {//如果是第一个tab
    5. if (customView == null) tab.setCustomView(R.layout.tab_text_layout)//设置布局
    6. val textView = customView?.findViewById(R.id.text1)
    7. textView?.text = titles[tab.position].i18n()
    8. textView?.setTextAppearance(requireContext(), R.style.TabLayoutTextSelected)//设置点击后的文本格式
    9. val point = customView?.findViewById(R.id.point_1)//这是tab右上角的红点
    10. val layoutParams = RelativeLayout.LayoutParams(SizeUtils.dp2px(8f), SizeUtils.dp2px(8f))
    11. layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP)
    12. layoutParams.addRule(RelativeLayout.END_OF, R.id.text1)
    13. layoutParams.setMargins(5, 0, 0, 0)
    14. point?.layoutParams = layoutParams
    15. } else {
    16. if (customView == null) tab.setCustomView(R.layout.tab_text_layout2)
    17. val textView = customView?.findViewById(R.id.tab_text2)
    18. textView?.text = titles[tab.position].i18n()
    19. textView?.setTextAppearance(requireContext(), R.style.TabLayoutTextSelected)
    20. }
    21. }

  • 相关阅读:
    插入排序(Java实现)
    Python 与 Qt c++ 程序共享内存,传递图片
    数据库系统 整体结构化 的理解
    Docker Stack部署应用详解+Tomcat项目部署详细实战
    某国外知名HR:参与开源贡献求职者的简历,直接扔掉
    23062C++&QTday5
    Spring Boot Actuator 管理日志
    LeetCode 面试题 16.25. LRU 缓存
    Java实现微信支付功能
    flink连接kafka报:org.apache.kafka.common.errors.TimeoutException
  • 原文地址:https://blog.csdn.net/LoveFHM/article/details/127685444
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号