Kotlin项目中使用BottomNavigationView实现底部导航效果

前言:底部导航切换页面一直是app开发的首选,这样既有利于页面的布局及功能模块的展示也有利于开发人员进行分模块的协同开发,现在大到与我们每天生活息息相关的支付宝与微信,小到普通的app都有底部导航切换页面的效果。本篇文章记录在kotlin项目中使用BottomNavigationView+ViewPager+Fragment实现底部导航切换页面效果。

实现方式

以下便是实现底部导航切换页面的五种实现方式,Tabhost的使用有些久远,现在已经基本不用;TabLayout和BottomNavigationView现在使用的比较多。

1.TabHost+Fragment方式实现

2.LinearLayout+TextView+Fragment方式实现

3.TabLayout+ViewPager+Fragment方式实现

4.RadioGroup+ViewPager+Fragment实现

5.BottomNavigationView+ViewPager+Fragment方式实现

效果图

BottomNavigationView(本文重点)

Android Design Support Library中增加了 BottomNavigationView 这个控件(API 25),BottomNavigationView为我们实现底部导航切换页面提供了方便,同时它也有着不便之处,比如:底部的条目个数超过三个,点击每个条目时会有很大的偏移量,且其它条目的图标则不会显示(文中通过反射解决);无法添加小红点的提示等问题。

1.添加依赖(25以上)

implementation 'com.android.support:design:26.1.0'

2.xml布局使用

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation_view"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_alignParentBottom="true"
    android:background="?android:attr/windowBackground"
    app:itemIconTint="@drawable/bottom_navigation_selector"
    app:itemTextColor="@drawable/bottom_navigation_selector"
    app:menu="@menu/bottom_navigation_menu">

</android.support.design.widget.BottomNavigationView>

itemIconTint属性:通过drawable设置点击和未点击时的图片颜色

itemTextColor属性:通过drawable设置点击和未点击时的字体颜色

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorRed" android:state_checked="true" />
    <item android:color="@color/colorFont" android:state_checked="false" />
</selector>

itemBackground属性:默认点击条目时的水波纹效果,如果不想要效果,可设置为@null

menu属性:就是我们定义的底部条目

(1)在res文件下创建menu文件夹

(2)在menu文件下创建条目的xml

(3)设置id、icon、title等属性

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/navigation_home"
        android:icon="@mipmap/navigation_home"
        android:title="首页" />
    <item
        android:id="@+id/navigation_technology"
        android:icon="@mipmap/navigation_technology"
        android:title="技术" />
    <item
        android:id="@+id/navigation_dynamic"
        android:icon="@mipmap/navigation_dynamic"
        android:title="动态" />
    <item
        android:id="@+id/navigation_mine"
        android:icon="@mipmap/navigation_mine"
        android:title="个人" />
</menu>

3.代码实现

注:kotlin可以通过id直接获取该控件的方法属性,不用再使用findViewById获取到控件(文中调用方法属性均是通过id实现的)

设置BottomNavigationView底部条目的点击监听

bottom_navigation_view.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
//通过反射解决超过3个条目的问题
BottomNavigationViewHelper.disableShiftMode(bottom_navigation_view)

mOnNavigationItemSelectedListener

private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
    menuItem = item
    when (item.itemId) {
        R.id.navigation_home -> {
            view_pager.currentItem = 0
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_technology -> {
            view_pager.currentItem = 1
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_dynamic -> {
            view_pager.currentItem = 2
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_mine -> {
            view_pager.currentItem = 3
            return@OnNavigationItemSelectedListener true
        }
    }
    false
}

4.解决条目超过4个的问题

通过查看BottomNavigationView的源码,我们发现mShiftMode属性控制了条目点击时缩放效果(即点击时设置了scaleX和scalxY为1,未点击的为0.5f)及图标是否显示(mLargeLabel的VISIBLE和INVISIBLE)

(1)mShiftingMode=true


(2)mShiftingMode=false


根据源码可知,只要我们设置mShiftingmode为false就能解决图标显示与不显示的问题

解决办法:由于BottomNavigationView无法通过代码直接来setShiftingMode的属性值(boolean类型),所以我们创建一个NavigationViewHelper并创建一个方法,通过反射获取到点击的BottomNavigationView条目,并设置它为false

fun disableShiftMode(view: BottomNavigationView) {
    //由于BottomNavigationView默认第一个为选中状态,所以我们首先获取第一个条目的menuView
    val menuView = view.getChildAt(0) as BottomNavigationMenuView

    try {
        val shiftingMode = menuView.javaClass.getDeclaredField("mShiftingMode")
        shiftingMode.isAccessible = true
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.isAccessible = false
        for (i in 0 until menuView.childCount) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            item.setChecked(item.itemData.isChecked)
        }
    } catch (e: NoSuchFieldException) {
        Log.e("rcw", "无法获取mShiftingMode属性", e)
    } catch (e: IllegalAccessException) {
        Log.e("rcw", "无法修改mShiftingMode属性值", e)
    }

}

BottomNavigationView+ViewPager

1.设置viewPager的page改变的监听

 
view_pager.addOnPageChangeListener(mOnPageChangedListener)
viewPagerAdapter= ViewPagerAdapter(supportFragmentManager)
view_pager.adapter=viewPagerAdapter
var list = ArrayList<Fragment>()
list.add(HomeFragment.newInstance("首页"))
list.add(TechnologyFragment.newInstance("技术"))
list.add(DynamicFragment.newInstance("动态"))
list.add(MineFragment.newInstance("个人"))
viewPagerAdapter!!.setList(list)
2.pageChangeListener中与BottomNavigationView关联

private val mOnPageChangedListener=object : ViewPager.OnPageChangeListener {
    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {

    }

    override fun onPageSelected(position: Int) {
        if (menuItem != null) {
            menuItem!!.isChecked = false
        } else {
            bottom_navigation_view.menu.getItem(0).isChecked = false
        }
        menuItem = bottom_navigation_view.menu.getItem(position)
        menuItem!!.isChecked = true
    }

    override fun onPageScrollStateChanged(state: Int) {

    }
}

由于ViewPagerAdapter的代码比较简单就不贴了!!!

以上就是kotlin中实现底布导航切换页面的核心代码,如有问题,欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值