文章目录
- 一、实现效果
- 二、引入依赖
- 三、实现源码
- ● 非左右滑动页面与底部导航栏
- 1、Fragment
- 2、视图实现
- ● 左右滑动页面与底部导航栏
- 1、页面适配器
- 2、视图实现
- 主页视图
- ______________________________________________
- 一、在底部导航栏中的居中Icon无title
- 二、BottomNavigationView常用属性
一、实现效果
二、引入依赖
在app
的build.gradle
在添加以下代码
implementation 'com.google.android.material:material:1.4.0'
三、实现源码
● 非左右滑动页面与底部导航栏
1、Fragment
1、4个页面代码,创建4个即可,创建方法相同,以下只示例一个
示例:Fragment1.kt
package com.demo.test.fragment
import com.demo.test.R
class Fragment1 : BaseFragment() {
override fun layoutRes(): Int = R.layout.fragment1
companion object {
fun newInstance() = Fragment1()
}
}
fragment1.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="match_parent"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="30dp"
android:text="首页"/>
</LinearLayout>
4个页面代码要继承父类BaseFragment()
,BaseFragment.kt
package com.demo.test.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
open class BaseFragment : Fragment(){
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(layoutRes(), container, false)
}
open fun layoutRes() = 0
}
2、视图实现
FragmentActivity.kt
package com.demo.test
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.demo.test.common.ScrollToTop
import com.demo.test.fragment.Fragment1
import com.demo.test.fragment.Fragment2
import com.demo.test.fragment.Fragment3
import com.demo.test.fragment.Fragment4
import kotlinx.android.synthetic.main.fragment.bottomNavigationView
import kotlinx.android.synthetic.main.fragment.viewPager
//非左右滑动页面与底部导航栏
class FragmentActivity : AppCompatActivity() {
private lateinit var fragments: Map<Int, Fragment>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.fragment)
viewPager.visibility = View.GONE
fragments = mapOf(
R.id.fragment1 to createFragment(Fragment1::class.java),
R.id.fragment2 to createFragment(Fragment2::class.java),
R.id.fragment3 to createFragment(Fragment3::class.java),
R.id.fragment4 to createFragment(Fragment4::class.java)
)
bottomNavigationView.run {
setOnNavigationItemSelectedListener { menuItem ->
showFragment(menuItem.itemId)
true
}
setOnNavigationItemReselectedListener { menuItem ->
val fragment = fragments.entries.find {
it.key == menuItem.itemId
}?.value
if (fragment is ScrollToTop) {
fragment.scrollToTop()
}
}
}
showBadgeView(2, 99)
if (savedInstanceState == null) {
val initialItemId = R.id.fragment1
bottomNavigationView.selectedItemId = initialItemId
showFragment(initialItemId)
}
}
private fun createFragment(clazz: Class<out Fragment>): Fragment {
var fragment = supportFragmentManager.fragments.find { it.javaClass == clazz }
if (fragment == null) {
fragment = when (clazz) {
Fragment1::class.java -> Fragment1.newInstance()
Fragment2::class.java -> Fragment2.newInstance()
Fragment3::class.java -> Fragment3.newInstance()
Fragment4::class.java -> Fragment4.newInstance()
else ->
throw IllegalArgumentException("argument ${clazz.simpleName} is illegal")
}
}
return fragment
}
private fun showFragment(menuItemId: Int) {
val currentFragment = supportFragmentManager.fragments.find {
it.isVisible && it in fragments.values
}
val targetFragment = fragments.entries.find {
it.key == menuItemId
}?.value
supportFragmentManager.beginTransaction().apply {
currentFragment?.let {
if (it.isVisible)
hide(it)
}
targetFragment?.let {
if (it.isAdded)
show(it)
else
add(R.id.fl, it)
}
}.commit()
}
/**
* BottomNavigationView显示角标
* @param viewIndex tab索引
* @param showNumber 显示的数字,小于等于0是将不显示
*/
private fun showBadgeView(viewIndex: Int, showNumber: Int) {
bottomNavigationView.getOrCreateBadge(R.id.fragment3).apply {
// backgroundColor = ContextCompat.getColor(this@FragmentActivity, R.color.red)
badgeTextColor = ContextCompat.getColor(this@FragmentActivity, R.color.white)
number = showNumber
}
// val menuItemId = bottomNavigationView.menu.getItem(viewIndex).itemId
// val badge : BadgeDrawable= bottomNavigationView.getOrCreateBadge(menuItemId)
// badge.number = showNumber
}
}
fragment.kt
,四个页面、底部带图标和文字的导航键
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:background="@drawable/ripple_item_select"
app:itemIconTint="@color/selector_bottom_navigation_item"
app:itemTextColor="@color/selector_bottom_navigation_item"
app:labelVisibilityMode="labeled"
app:menu="@menu/menu_bottom_navigation" />
</LinearLayout>
ripple_item_select.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/colorRipple">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/bgColorPrimary" /><!--<color name="bgColorPrimary">#FFFFFF</color>-->
</shape>
</item>
</selector>
selector_bottom_navigation_item.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <color name="colorAccent">#D82637</color> -->
<item android:color="@color/colorAccent" android:state_checked="true" />
<!-- <color name="textColorThird">#9297A2</color> -->
<item android:color="@color/textColorThird" android:state_checked="false" />
</selector>
使用menu
属性定义底部条目:
- 在
res
文件下创建menu
文件夹- 在
menu
文件下创建条目的menu_bottom_navigation.xml
- 设置
id
、icon
、title
等属性
四个icon图标是在在android studio
系统中添加资源图标
在AndroidManifest.xml
中的application
下的改主题:
android:theme="@style/AppTheme">
在styles.xml
中改主题:
ScrollToTop.kt
package com.demo.test.common
/**
* Created by xiaojianjun on 2019-11-15.
*/
interface ScrollToTop {
fun scrollToTop()
}
● 左右滑动页面与底部导航栏
1、页面适配器
MyPagerAdapter.kt
package com.demo.test.pager
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
class MyPagerAdapter(fm: FragmentManager, private val fragmentList:MutableList<Fragment>) : FragmentStatePagerAdapter(fm) {
override fun getCount(): Int {
return fragmentList.size
}
override fun getItem(position: Int): Fragment {
return fragmentList[position]
}
}
2、视图实现
FragmentAndPageSlideActivity.kt
package com.demo.test
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import com.demo.test.pager.MyPagerAdapter
import com.demo.test.fragment.Fragment2
import com.demo.test.fragment.Fragment3
import com.demo.test.fragment.Fragment4
import com.demo.test.fragment.Fragment1
import kotlinx.android.synthetic.main.fragment.*
//左右滑动页面与底部导航栏
class FragmentAndPageSlideActivity : AppCompatActivity() {
private var fragmentList: MutableList<Fragment> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.fragment)
fl.visibility = View.GONE
initData()
val adapter = MyPagerAdapter(supportFragmentManager, fragmentList)
viewPager.adapter = adapter
//页面更改监听
viewPager.setOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
override fun onPageSelected(position: Int) {
when (position) {
0 -> bottomNavigationView.selectedItemId = R.id.fragment1
1 -> bottomNavigationView.selectedItemId = R.id.fragment2
2 -> bottomNavigationView.selectedItemId = R.id.fragment3
3 -> bottomNavigationView.selectedItemId = R.id.fragment4
}
}
override fun onPageScrollStateChanged(state: Int) {
}
})
//图标选择监听
bottomNavigationView.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.fragment1 -> viewPager.currentItem = 0
R.id.fragment2 -> viewPager.currentItem = 1
R.id.fragment3 -> viewPager.currentItem = 2
R.id.fragment4 -> viewPager.currentItem = 3
}
return@setOnNavigationItemSelectedListener true
}
}
private fun initData() {
val fragment1 = Fragment1.newInstance()
fragmentList.add(fragment1)
val fragment2 = Fragment2.newInstance()
fragmentList.add(fragment2)
val fragment3 = Fragment3.newInstance()
fragmentList.add(fragment3)
val fragment4 = Fragment4.newInstance()
fragmentList.add(fragment4)
}
}
主页视图
MainActivity.kt
package com.demo.test
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//非左右滑动页面与底部导航栏
button1.setOnClickListener {
val intent = Intent(this@MainActivity, FragmentActivity::class.java)
startActivity(intent)
}
//左右滑动页面与底部导航栏
button2.setOnClickListener {
val intent = Intent(this@MainActivity, FragmentAndPageSlideActivity::class.java)
startActivity(intent)
}
}
}
activity_main.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="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="非左右滑动页面与底部导航栏"
android:textColor="@color/black"/>
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="左右滑动页面与底部导航栏"
android:textColor="@color/black"/>
</LinearLayout>
______________________________________________
一、在底部导航栏中的居中Icon无title
如下图:
修改代码:
<?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">
<TextView
android:id="@+id/tvHeaderTitle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/white"
android:elevation="2dp"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:text="@string/main_mine"
android:textColor="@color/purple"
android:textSize="@dimen/dp_18"
app:layout_constraintTop_toTopOf="parent"/>
<FrameLayout
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvHeaderTitle"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/white"
app:elevation="8dp"
app:itemIconSize="29dp"
app:itemIconTint="@color/selector_bottom_navigation_item"
app:itemRippleColor="@color/yellow"
app:itemTextColor="@color/selector_bottom_navigation_item"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/menu_bottom_navigation"/>
<ImageView
android:id="@+id/navigation_center_image"
android:layout_width="29dp"
android:layout_height="29dp"
android:layout_gravity="center"
android:elevation="10dp"
android:src="@drawable/ic_add"
app:layout_constraintBottom_toBottomOf="@id/bottomNavigationView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/bottomNavigationView" />
</androidx.constraintlayout.widget.ConstraintLayout>
menu_bottom_navigation.xml,如下图:
二、BottomNavigationView常用属性
-
app:itemIconTint
:指定底部导航栏元素图标的着色方式,默认元素选中是iocn
颜色为@color/colorPrimary
-
app:itemTextColor
:指定底部导航栏元素文字的着色方式 -
app:menu
:使用Menu
的形式为底部导航栏指定元素 -
app:itemIconSize
:图标大小,默认24dp
app:labelVisibilityMode
:文字的显示模式
-
labeled
:保持所有文字便签显示 -
unlabeled
:只显示图标 -
selected
:在选中的时候显示文字标签,有动画效果 -
auto
:在1-3个按钮时使用labeled
,大于3个按钮使用selected
-
app:itemRippleColor
:点击后的水波纹颜色 -
app:elevation
:控件顶部的阴影