Kotlin項目中使用BottomNavigationView實現(xiàn)底部導(dǎo)航效果

前言:底部導(dǎo)航切換頁面一直是app開發(fā)的首選,這樣既有利于頁面的布局及功能模塊的展示也有利于開發(fā)人員進行分模塊的協(xié)同開發(fā),現(xiàn)在大到與我們每天生活息息相關(guān)的支付寶與微信,小到普通的app都有底部導(dǎo)航切換頁面的效果。本篇文章記錄在kotlin項目中使用BottomNavigationView+ViewPager+Fragment實現(xiàn)底部導(dǎo)航切換頁面效果。

實現(xiàn)方式

以下便是實現(xiàn)底部導(dǎo)航切換頁面的五種實現(xiàn)方式,Tabhost的使用有些久遠,現(xiàn)在已經(jīng)基本不用;TabLayout和BottomNavigationView現(xiàn)在使用的比較多。

1.TabHost+Fragment方式實現(xiàn)

2.LinearLayout+TextView+Fragment方式實現(xiàn)

3.TabLayout+ViewPager+Fragment方式實現(xiàn)

4.RadioGroup+ViewPager+Fragment實現(xiàn)

5.BottomNavigationView+ViewPager+Fragment方式實現(xiàn)

效果圖

image

BottomNavigationView(本文重點)

Android Design Support Library中增加了 BottomNavigationView 這個控件(API 25),BottomNavigationView為我們實現(xiàn)底部導(dǎo)航切換頁面提供了方便,同時它也有著不便之處,比如:底部的條目個數(shù)超過三個,點擊每個條目時會有很大的偏移量,且其它條目的圖標則不會顯示(文中通過反射解決);無法添加小紅點的提示等問題。

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設(shè)置點擊和未點擊時的圖片顏色

itemTextColor屬性:通過drawable設(shè)置點擊和未點擊時的字體顏色

 <item android:color="@color/colorRed" android:state_checked="true" />
 <item android:color="@color/colorFont" android:state_checked="false" /> </selector>

itemBackground屬性:默認點擊條目時的水波紋效果,如果不想要效果,可設(shè)置為@null

menu屬性:就是我們定義的底部條目

(1)在res文件下創(chuàng)建menu文件夾

(2)在menu文件下創(chuàng)建條目的xml

(3)設(shè)置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="技術(shù)" />
 <item  android:id="@+id/navigation_dynamic"
      android:icon="@mipmap/navigation_dynamic"
      android:title="動態(tài)" />
 <item  android:id="@+id/navigation_mine"
      android:icon="@mipmap/navigation_mine"
      android:title="個人" /> 
</menu>

3.代碼實現(xiàn)

注:kotlin可以通過id直接獲取該控件的方法屬性,不用再使用findViewById獲取到控件(文中調(diào)用方法屬性均是通過id實現(xiàn)的)

設(shè)置BottomNavigationView底部條目的點擊監(jiān)聽

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個的問題

A.通過查看BottomNavigationView的源碼,我們發(fā)現(xiàn)mShiftMode屬性控制了條目點擊時縮放效果(即點擊時設(shè)置了scaleX和scalxY為1,未點擊的為0.5f)及圖標是否顯示(mLargeLabel的VISIBLE和INVISIBLE)

(1)mShiftingMode=true

image

(2)mShiftingMode=false

image

根據(jù)源碼可知,只要我們設(shè)置mShiftingmode為false就能解決圖標顯示與不顯示的問題

B.解決辦法:由于BottomNavigationView無法通過代碼直接來setShiftingMode的屬性值(boolean類型),所以我們創(chuàng)建一個NavigationViewHelper并創(chuàng)建一個方法,通過反射獲取到點擊的BottomNavigationView條目,并設(shè)置它為false

fun disableShiftMode(view: BottomNavigationView) {
    //由于BottomNavigationView默認第一個為選中狀態(tài),所以我們首先獲取第一個條目的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.設(shè)置viewPager的page改變的監(jiān)聽

view_pager.addOnPageChangeListener(mOnPageChangedListener)
viewPagerAdapter= ViewPagerAdapter(supportFragmentManager)
view_pager.adapter=viewPagerAdapter
var list = ArrayList<Fragment>()
list.add(HomeFragment.newInstance("首頁"))
list.add(TechnologyFragment.newInstance("技術(shù)"))
list.add(DynamicFragment.newInstance("動態(tài)"))
list.add(MineFragment.newInstance("個人"))
viewPagerAdapter!!.setList(list)

2.pageChangeListener中與BottomNavigationView關(guān)聯(lián)

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中實現(xiàn)底布導(dǎo)航切換頁面的核心代碼,如有問題,歡迎指正!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容