The common high-level components of Android can be combined to build a common interface structure for mobile applications, as shown in the figure below:
The above interface can be found to have a side-sliding menu, and the home button, application title and menu can be displayed at the top of the main content area of the interface. There is a navigation bar at the bottom for easy navigation. The side-sliding menu and bottom navigation make it easy to switch between interface contents.
Such a universal interface can be applied in a variety of applications and is very convenient to use.
1. Define the top toolbar and side sliding menu
(1) The layout activity_main.xml corresponding to MainActivity is as follows:
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawerLayout"
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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<**androidx.appcompat.widget.Toolbar**
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</RelativeLayout>
</androidx.drawerlayout.widget.DrawerLayout>
In the above layout, DrawerLayout and NavigationView are combined to define the side sliding menu. A Toolbar is defined in the content area.
(2) To set the custom Toolbar to the default ActionBar,
you need to configure it in the application configuration file AndroidManifest.xml as follows:
<activity
android:name=".MainActivity"
**android:theme="@style/Theme.AppCompat.NoActionBar"**
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Set the theme dimension NoActionBar of the MainActivity activity to provide convenience for setting the Toolbar as an action bar.
(3) Set Toolbar as a supported action bar in MainActivity.kt
setSupportActionBar(binding.toolbar)
(4) Define the menu on the action bar:
Assume that menu.xml is created in the res/menu/ directory with the following content:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="菜单"
android:icon="@mipmap/ic_launcher"
app:showAsAction="always">
<menu>
<item
android:id="@+id/aboutItem"
android:icon="@android:drawable/ic_dialog_info"
android:title="关于我们"
app:showAsAction="always" />
<item
android:id="@+id/exitItem"
android:icon="@android:drawable/ic_notification_clear_all"
android:title="退出应用"
app:showAsAction="always" />
</menu>
</item>
</menu>
This is a second-level menu. The first-level menu is displayed as an icon. Click to pop up the second-level menu, so that the second-level menu can display the menu title and icon at the same time.
(5) Modify the MainActivity.kt code and add menu processing:
class MainActivity : AppCompatActivity() {
lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
configToolbar()
setContentView(binding.root)
}
fun configToolbar(){
setSupportActionBar(binding.toolbar)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu,menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.aboutItem-> Toast.makeText(MainActivity@this,"Testing...",Toast.LENGTH_LONG).show()
R.id.exitItem-> exitProcess(0)
}
return true
}
}
(6) To add the NavigationView of the side-sliding menu, you need to modify the activity_main.xml layout file as follows:
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawerLayout"
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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</RelativeLayout>
**<com.google.android.material.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:headerLayout="@layout/header_layout"
app:menu="@menu/menu_navigation"
android:layout_gravity="start"
/>**
</androidx.drawerlayout.widget.DrawerLayout>
Among them,
the corresponding definition in the NavigationView element
app:headerLayout="@layout/header_layout":
is header_layout.xml in the layout directory, which represents the header layout of the side-sliding menu. The specific definition is omitted; the
app:menu="@menu/menu_navigation":
corresponding content of the navigation menu in the lower part of the side-sliding menu corresponds to menu_navigation in the res/menu directory. .xml, the code is as follows:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/favorityItem"
android:title="我的收藏" android:icon="@android:drawable/btn_star" />
<item
android:id="@+id/appItem"
android:title="关于应用" android:icon="@android:drawable/ic_dialog_info"/>
<item
android:id="@+id/configItem"
android:title="系统配置" android:icon="@android:drawable/ic_menu_manage"/>
</menu>
Modify MainActivity.kt to add processing for side-sliding menus
class MainActivity : AppCompatActivity() {
lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
configToolbar()
configDrawer()
setContentView(binding.root)
}
fun configToolbar(){
setSupportActionBar(binding.toolbar)
}
fun configDrawer(){
supportActionBar?.let{
it.setDisplayHomeAsUpEnabled(true)
it.setHomeAsUpIndicator(R.mipmap.ic_launcher)
}
binding.navigationView.itemIconTintList = null
binding.navigationView.setCheckedItem(R.id.favorityItem)
binding.navigationView.setNavigationItemSelectedListener {
when(it.itemId){
R.id.favorityItem->Snackbar.make(binding.drawerLayout,"FAVORITE",
Snackbar.LENGTH_LONG).setAction("点击"){
exitProcess(0)
}.show()
R.id.appItem->Toast.makeText(this,"APP",Toast.LENGTH_LONG).show()
R.id.configItem->Toast.makeText(this,"CONFIG",Toast.LENGTH_LONG).show()
}
binding.drawerLayout.closeDrawer(GravityCompat.START)
true
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu,menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
android.R.id.home->binding.drawerLayout.openDrawer(GravityCompat.START)
R.id.aboutItem-> Toast.makeText(MainActivity@this,"Testing...",Toast.LENGTH_LONG).show()
R.id.exitItem-> exitProcess(0)
}
return true
}
}
Explanation of the above code:
(a) Code:
supportActionBar?.let{
it.setDisplayHomeAsUpEnabled(true)
it.setHomeAsUpIndicator(R.mipmap.ic_launcher)
}
The two functions called by the above code block are ic_launcher that allows the top Home button to be displayed and sets the icon of the top Home button to the res/mipmap directory.
(b)Code:
binding.navigationView.setNavigationItemSelectedListener {
when(it.itemId){
R.id.favorityItem->Snackbar.make(binding.drawerLayout,"FAVORITE",
Snackbar.LENGTH_LONG).setAction("点击"){
exitProcess(0)
}.show()
R.id.appItem->Toast.makeText(this,"APP",Toast.LENGTH_LONG).show()
R.id.configItem->Toast.makeText(this,"CONFIG",Toast.LENGTH_LONG).show()
}
binding.drawerLayout.closeDrawer(GravityCompat.START)
true
}
}
Add navigation processing for the navigation menu of the side-sliding menu. Here we simply process the interactive message box Toast and close the side sliding menu through binding.drawerLayout.closeDrawer(GravityCompat.START).
(c) You still need to add a Home button to the Toolbar. Click the Home button to display the side-sliding menu.
Add it to onOptionsItemSelected.
when(item.itemId){
**android.R.id.home->binding.drawerLayout.openDrawer(GravityCompat.START)**
...
}
Here android.R.id.home corresponds to the Home key, as shown in the running results:
(7) Define the bottom navigation view BottomNavigationView
(a) Modify the activity_main.xml layout
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawerLayout"
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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_toEndOf="@+id/btView"
/>
**<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/btView"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:menu="@menu/menu_navigation"
android:layout_alignParentBottom="true"/>**
</RelativeLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:headerLayout="@layout/header_layout"
app:menu="@menu/menu_navigation"
android:layout_gravity="start"
/>
</androidx.drawerlayout.widget.DrawerLayout>
(b) Define and modify MainActivity to add the bottom navigation view BottomNavigationView processing
class MainActivity : AppCompatActivity() {
lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
configToolbar()
configDrawer()
configBottomNavigationView()
setContentView(binding.root)
}
fun configToolbar(){
setSupportActionBar(binding.toolbar)
}
fun configDrawer(){
supportActionBar?.let{
it.setDisplayHomeAsUpEnabled(true)
it.setHomeAsUpIndicator(R.mipmap.ic_launcher)
}
binding.navigationView.itemIconTintList = null
binding.navigationView.setCheckedItem(R.id.favorityItem)
binding.navigationView.setNavigationItemSelectedListener {
when(it.itemId){
R.id.favorityItem->Snackbar.make(binding.drawerLayout,"FAVORITE",
Snackbar.LENGTH_LONG).setAction("点击"){
exitProcess(0)
}.show()
R.id.appItem->Toast.makeText(this,"APP",Toast.LENGTH_LONG).show()
R.id.configItem->Toast.makeText(this,"CONFIG",Toast.LENGTH_LONG).show()
}
binding.drawerLayout.closeDrawer(GravityCompat.START)
true
}
}
fun configBottomNavigationView(){
binding.btView.itemIconTintList = null
binding.btView.setOnItemSelectedListener {
when(it.itemId){
R.id.favorityItem->Snackbar.make(binding.drawerLayout,"FAVORITE",
Snackbar.LENGTH_LONG).setAction("点击"){
exitProcess(0)
}.show()
R.id.appItem->Toast.makeText(this,"APP",Toast.LENGTH_LONG).show()
R.id.configItem->Toast.makeText(this,"CONFIG",Toast.LENGTH_LONG).show()
}
true
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu,menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
android.R.id.home->binding.drawerLayout.openDrawer(GravityCompat.START)
R.id.aboutItem-> Toast.makeText(MainActivity@this,"Testing...",Toast.LENGTH_LONG).show()
R.id.exitItem-> exitProcess(0)
}
return true
}
}
References
"Android Mobile Application Development (Micro Course Edition)" Chen Yi Tsinghua University Press
ISBN: 978-7-302-59734-6