首先需要导入的是design库,可以是:androidx 的引入,或support库的引入
//androidx 引入design库的方式
implementation 'com.google.android.material:material:1.0.0-rc01'
//或者support 引入design库的方式
//implementation ‘com.android.support:design:28.0.0’
首先MainActivity 的 Layout 布局:
最外层用DrawerLayout 给包起来 ,然后在用CoordinatorLayout(Design 库中的一个可伸展的布局,内部嵌套一个toolbar 和 Fragment 需展示的container 页面),然后在该布局中的底部添加一个BottomNavigationView 的底部多Tab的控件(由google 官方自己封装好的一个多Tab选择切换控件),然后是NavigationView(抽屉布局的具体layout)
toolbar.xml 如下:
外部由AppBarLayout 包含,内部是Toolbar,然后是toolbar上的按钮和标题。
以及Toolbar顶部的按钮自定义style.xml :
container.xml
就是一个帧布局,用来做Fragment 显示内容的载体
底部BottomNavigationView 的menu 布局,navigation_bottom.xml :需将其放入menu 目录下的
展示其中一个item的drawable ,如ic_wechat,xml ,是svg 矢量图
以及点击底部Item的selector,nav_item_color_selector.xml :
最后是抽屉布局中nav_header.xml : 就是上图中抽屉布局上部的图片区域
以及其底部的item菜单,menu_drawer.xml ,也是需要放入menu 目录中的:
还有顶部的扫一扫按钮和查询按钮的布局文件,也是一个menu 文件,需放入menu目录下,menu_activity_main.xml:
好了,讲完了其layout,接下来讲解其MainActivity.kt 其代码逻辑 , 下述代码由kotlin,所写,java的会日后再补上。MainActivity.kt 代码如下:
package com.cx.icxwanandroid.ui
import android.content.Context
import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment
import com.cx.icxwanandroid.R
import com.cx.icxwanandroid.base.BaseActivity
import com.cx.icxwanandroid.ui.fragment.*
import com.cx.icxwanandroid.utils.ToastUtils
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomnavigation.LabelVisibilityMode.LABEL_VISIBILITY_LABELED
import com.google.android.material.navigation.NavigationView
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.toolbar.*
import java.lang.Exception
class MainActivity : BaseActivity() {
private var mCurrentFragment : Fragment ?= null
private var index : Int = 0
private var fragmentTag : String ?= null
//每个Fragment 的Tag
private val fragmentNames = arrayOf(
HomeFragment::class.java.name,
WeChatFragment::class.java.name,
ProjectFragment::class.java.name,
NavigationFragment::class.java.name,
KnowledgeTreeFragment::class.java.name
)
//底部的tab的Title
private val bottomTitles = arrayOf(
R.string.home , R.string.wechat , R.string.project , R.string.navigation , R.string.konwledge_tree
)
override var layoutId: Int = R.layout.activity_main
override fun initData() {
//设置toolBar
setSupportActionBar(toolbar)
//初始化抽屉布局
initDrawerLayout()
//初始化抽屉布局中的item 的点击事件
initNav()
//设置底部Tab的点击事件
initNavBottom()
//设置底部的切换Tab 导致切换Fragment的逻辑
bottomNav()
}
override fun subscibeUi() {
}
//初始化整个抽屉的布局,并且设置抽屉按钮开启和关闭的点击事件
private fun initDrawerLayout(){
drawer_layout.run {
val toggle = ActionBarDrawerToggle(
this@MainActivity,
this,
toolbar,
R.string.app_name,
R.string.app_name
)
addDrawerListener(toggle)
toggle.syncState()
}
}
//设置抽屉item 的点击事件
private fun initNav(){
val navListener = NavigationView.OnNavigationItemSelectedListener{
when(it.itemId){
R.id.favorites -> {
}
R.id.todo -> {
}
R.id.night_mode -> {
}
R.id.setting -> {
}
R.id.logout -> {
}
R.id.about -> {
}
}
drawer_layout.closeDrawer(GravityCompat.START)
true
}
nav_view.run {
setNavigationItemSelectedListener(navListener)
}
}
//初始化底部Tab的点击事件
private fun initNavBottom(){
val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener {
item ->
when(item.itemId){
R.id.home -> index = 0
R.id.wechat -> index = 1
R.id.project -> index = 2
R.id.navigation -> index = 3
R.id.knowledge_tree -> index = 4
}
bottomNav()
true
}
navigation_bottom.run {
labelVisibilityMode = LABEL_VISIBILITY_LABELED
setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
}
private fun bottomNav(){
toolbar.title = getString(
if(index == 0){
R.string.app_name
}else{
bottomTitles[index]
}
)
//设置toolBar 的Title颜色
toolbar.setTitleTextColor(Color.parseColor("#ffffff"))
fragmentTag = fragmentNames[index]
val fragment = getFragmentByTag(fragmentTag!!)
showFragment(mCurrentFragment , fragment , fragmentTag!!)
}
//根据FragmentTag 得到 Fragment
private fun getFragmentByTag(name : String) : Fragment{
var fragment = supportFragmentManager.findFragmentByTag(name)
if(fragment != null){
return fragment
} else {
try {
// 得到Fragment的实例
fragment = Class.forName(name).newInstance() as Fragment
}catch (e : Exception){
fragment = HomeFragment()
}
}
return fragment!!
}
//显示Fragment
private fun showFragment(from : Fragment ? , to : Fragment , tag : String){
val transaction = supportFragmentManager.beginTransaction()
if(from == null){
if(to.isAdded){
transaction.show(to)
}else{
transaction.add(R.id.container , to , tag)
}
}else{
if(to.isAdded){
transaction.hide(from).show(to)
}else{
transaction.hide(from).add(R.id.container , to , tag)
}
}
transaction.commit()
mCurrentFragment = to
}
//初始化顶部的菜单,有扫一扫和查询按钮
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_activity_main , menu)
return super.onCreateOptionsMenu(menu)
}
//顶部扫一扫和查询的点击事件
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.scan -> {
ToastUtils.show("scan")
return true
}
R.id.search -> {
ToastUtils.show("search")
return true
}
}
return super.onOptionsItemSelected(item)
}
}
BaseActivity.kt 代码如下:
package com.cx.icxwanandroid.base
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
abstract class BaseActivity : AppCompatActivity() {
protected abstract var layoutId : Int
// protected var multipleStatusView : MultipleStatusView ?= null
protected abstract fun initData()
protected abstract fun subscibeUi()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(layoutId)
initData()
subscibeUi()
}
}
BaseFragment 代码如下:
package com.cx.icxwanandroid.base
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
abstract class BaseFragment : Fragment(){
protected abstract var layoutId : Int
protected abstract fun initData()
protected abstract fun subscribeUi()
open fun onRetry(){
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(layoutId , container , false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initData()
subscribeUi()
}
}
好啦,写到这里就结束了,基础的页面框架,Android 抽屉布局 + 底部多 Tab切换 + 自定义ToolBar 的UI 效果就已经搭好啦,读者可以参考代码去实现哈!