kotlin顶部导航栏(TabLayout+viewpager)、底部导航栏(谷歌官方-修复Navigation重建Fragment问题)、TabLayout单选

一、顶部导航栏(TabLayout+viewpager)

简介

使用google原生推荐的TabLayout+viewpager,超级好用,而且性能上已经是优化到最好了,超级推荐大家这样用,代码的每个细节的作用和功能我都已经标明,下面来看看效果图:
在这里插入图片描述

在这里插入图片描述

代码

MainActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
        val viewPager: ViewPager = findViewById(R.id.view_pager)
        viewPager.adapter = sectionsPagerAdapter
        val tabs: TabLayout = findViewById(R.id.tabs)
        tabs.setupWithViewPager(viewPager)

    }
}

SectionsPagerAdapter

class SectionsPagerAdapter(private val context: Context, fm: FragmentManager)
    : FragmentPagerAdapter(fm) {
    //顶部tablayout的字符
    private val TAB_TITLES = arrayOf(
        R.string.tab_text_1,
        R.string.tab_text_2,
        R.string.tab_text_3,
        R.string.tab_text_4

    )

    override fun getItem(position: Int): Fragment {
        // 顶部有多少个tab,就会运行多少次(初次会加载第一第二,第三第四要点第三个tab才会运行)
        /*******新建Fragment******/
        Log.d("WY+","运行第几次:"+(position+1))
         when (position) {
            0 -> {
                return PlaceholderFragment.newInstance(position + 1)
            }
            1 -> {
                return PlaceholderFragment.newInstance(position + 1)
            }
            2 -> {
                return ThreeFragment.newInstance(0)
            }
            3 -> {
                return FourFragment.newInstance(0)
            }
        }
        return PlaceholderFragment.newInstance(position + 1)

    }

    override fun getPageTitle(position: Int): CharSequence? {
        return context.resources.getString(TAB_TITLES[position])
    }

    override fun getCount(): Int {
        // 顶部显示多少个页,不要超过TAB_TITLES的总数.
        return 4
    }
}

PageViewModel

class PageViewModel : ViewModel() {

    private val _index = MutableLiveData<Int>()


    val text: LiveData<String> = Transformations.map(_index) {

        "Hello world from section: $it"


    }

    fun setIndex(index: Int) {
        _index.value = index
    }
}

ThreeFragment

class ThreeFragment : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.fragment_three, container, false)

        return root
    }

    companion object {
        /**
         * 单例,返回给定节编号的此片段的新实例。
         */
        @JvmStatic
        fun newInstance(sectionNumber: Int): ThreeFragment {
            return ThreeFragment().apply {

            }
        }
    }
}

PlaceholderFragment

class PlaceholderFragment : Fragment() {

    private lateinit var pageViewModel: PageViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

//        实例一个PageViewModel,object.apply返回一个自身的对象(object),apply可以赋值一个类里面的属性和调用方法
        pageViewModel = ViewModelProviders.of(this).get(PageViewModel::class.java).apply {
            setIndex(arguments?.getInt(ARG_SECTION_NUMBER) ?: 1)
        }

    }

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.fragment_main, container, false)
        val textView: TextView = root.findViewById(R.id.section_label)

        pageViewModel.text.observe(viewLifecycleOwner, Observer<String> {
            Log.d("WY+", "===>$it")
            textView.text = it

        })
        return root
    }

    companion object {
        private const val ARG_SECTION_NUMBER = "section_number"

        /**
         * 返回给定节编号的此片段的新实例。
         */
        @JvmStatic
        fun newInstance(sectionNumber: Int): PlaceholderFragment {
            return PlaceholderFragment().apply {
                arguments = Bundle().apply {
                    putInt(ARG_SECTION_NUMBER, sectionNumber)
                }
            }
        }
    }
}

FourFragment

class FourFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.fragment_four, container, false)

        return root
    }

    companion object {
        /**
         * 单例,返回给定节编号的此片段的新实例。
         */
        @JvmStatic
        fun newInstance(sectionNumber: Int): ThreeFragment {
            return ThreeFragment().apply {

            }
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="?attr/colorPrimary" />
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.fragment.PlaceholderFragment">

    <TextView
        android:id="@+id/section_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/activity_horizontal_margin"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:layout_marginEnd="@dimen/activity_horizontal_margin"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintTop_creator="1" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_three.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.fragment.PlaceholderFragment">

    <TextView
        android:id="@+id/section_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        android:text="独立的fragment3" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_four.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.fragment.PlaceholderFragment">

    <TextView
        android:id="@+id/section_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
        android:text="2222" />
</androidx.constraintlayout.widget.ConstraintLayout>

最后想要demo的朋友可到这里下载:https://download.csdn.net/download/wy313622821/12520093

注意:谷歌原生的代码布局是使用CoordinatorLayout,在配合底部导航栏使用时,切换其他的页面时会产生一个空白的区域,解决这个问题就是把CoordinatorLayout换成ConstraintLayout

二、TabLayout单独使用

在这里插入图片描述

代码地址为:https://download.csdn.net/download/wy313622821/87759169

三、TabLayout结合viewpager(推荐)

效果图:
在这里插入图片描述

viewpage2代码地址:点我
代码地址:链接

四、简单的顶部导航栏(自定义view+viewpager)(不推荐)

效果图如下:
在这里插入图片描述
代码下载:https://download.csdn.net/download/wy313622821/87512569

五、底部导航栏(谷歌官方)

在这里插入图片描述
试用BottomNavigationView时,如果底部的菜单项多于3个时,除第一个外都只显示图标,而不显示文字。
在这里插入图片描述
解决办法:
bottomNavigationView.labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED

需要代码的可以到这里下载:
https://download.csdn.net/download/wy313622821/22764527

修复底部栏切换会重新建fragment问题
需要代码的可以到这里下载:https://download.csdn.net/download/wy313622821/87356129

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
实现 ViewPager2+TabLayout+Fragment 实现页面切换,需要以下步骤: 1. 在 XML 布局文件中定义 ViewPager2 和 TabLayout,并将它们嵌套在一个父布局中。 ```xml <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="scrollable" app:tabGravity="center"/> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@id/tab_layout" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> ``` 2. 创建 Fragment,并实现 ViewPager2 的适配器。 ```kotlin class MyFragmentAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) { private val fragmentList = listOf( FirstFragment(), SecondFragment(), ThirdFragment() ) override fun getItemCount() = fragmentList.size override fun createFragment(position: Int) = fragmentList[position] } ``` 3. 在 Activity 或 Fragment 中,初始化 ViewPager2 和 TabLayout,并将适配器设置给 ViewPager2。 ```kotlin val viewPager: ViewPager2 = findViewById(R.id.view_pager) val tabLayout: TabLayout = findViewById(R.id.tab_layout) val adapter = MyFragmentAdapter(this) viewPager.adapter = adapter TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = "Tab ${position + 1}" }.attach() ``` 这样就可以实现 ViewPager2+TabLayout+Fragment 实现页面切换了。注意,TabLayoutMediator 是用来关联 TabLayout 和 ViewPager2 的,它的第一个参数是 TabLayout,第二个参数是 ViewPager2,第三个参数是一个回调函数,用来设置 TabLayout 的标签文本。在最后一行调用 attach() 方法即可完成关联。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wy313622821

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值