一、项目介绍
在现代 Android 应用中,顶部导航栏(通常指 Toolbar
或 AppBarLayout
)承担着显示页面标题、导航按钮和操作菜单的职责。一个优秀的顶部导航栏应当具备:
-
品牌识别:显示应用 Logo 或标题;
-
导航返回:支持“向上”或“返回”按钮;
-
操作入口:在右侧提供关键操作(搜索、更多菜单、切换视图);
-
风格统一:与应用主题完美融合;
-
可扩展:可在布局中或代码里动态更换标题、菜单、Logo。
本教程演示在 AndroidX/AppCompat 环境下,如何从零搭建一个功能完备的顶部导航栏,涵盖:
-
使用
Toolbar
代替原生ActionBar
-
在 XML 中声明与配置;
-
在
Activity
中通过setSupportActionBar()
绑定并处理菜单、导航点击; -
自定义
Toolbar
布局(添加搜索框、TabLayout 等); -
主题与样式配置以适配深色/浅色模式;
-
演示集成到单一
MainActivity.java
文件中的所有资源。
二、相关技术与知识
-
AppCompat Toolbar
-
androidx.appcompat.widget.Toolbar
:支持自定义视图、菜单、Logo、导航图标;
-
-
Menu 与 MenuItem
-
在
res/menu/
下定义<menu>
,通过onCreateOptionsMenu()
加载; -
使用
onOptionsItemSelected()
处理点击事件;
-
-
主题与样式
-
在
styles.xml
中使用ThemeOverlay.AppCompat.Dark.ActionBar
或自定义toolbarStyle
; -
通过
android:popupTheme
指定溢出菜单的样式;
-
-
导航图标
-
toolbar.setNavigationIcon()
或在 XML 中app:navigationIcon="@drawable/ic_back"
; -
通过
toolbar.setNavigationOnClickListener()
处理返回逻辑。
-
-
自定义布局
-
toolbar.inflateMenu()
、toolbar.addView()
或在 XML 内嵌自定义布局; -
可结合
TabLayout
、SearchView
实现更丰富的导航栏。
-
-
兼容与性能
-
AppCompat 库确保在 Android 4.1+ 上支持
Toolbar
; -
使用矢量图(
VectorDrawable
)节省资源。
-
三、实现思路
-
主题配置
-
在
styles.xml
定义应用主题AppTheme
,设置windowActionBar=false
,windowNoTitle=true
; -
定义
Toolbar
样式MyToolbarStyle
,包括背景色、标题文本外观、溢出菜单主题;
-
-
布局
-
在
activity_main.xml
中使用LinearLayout
或CoordinatorLayout
,将Toolbar
放在最上方,下面放置主内容; -
在
Toolbar
中通过 XML 属性指定app:logo
、app:title
、app:subtitle
、app:navigationIcon
;
-
-
菜单资源
-
在
res/menu/main_menu.xml
中定义若干<item>
,指定android:icon
、android:title
、app:showAsAction="ifRoom"
;
-
-
Activity 绑定
-
在
MainActivity.onCreate()
中调用setSupportActionBar(toolbar)
; -
在
onCreateOptionsMenu()
中加载菜单; -
在
onOptionsItemSelected()
中处理菜单与导航点击;
-
-
扩展:自定义布局
-
演示如何在
Toolbar
中间放置一个搜索EditText
; -
演示如何结合
TabLayout
实现顶部选项卡。
-
四、完整代码
// ==============================================
// 文件:MainActivity.java
// 功能:演示如何实现顶部导航栏(Toolbar)
// 将以下资源整合在此文件注释中:
// - AndroidManifest.xml 关键节点
// - styles.xml
// - layout/activity_main.xml
// - menu/main_menu.xml
// - drawable/ic_back.xml (返回图标示例)
// ==============================================
package com.example.toptoolbar;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/*
=========================== AndroidManifest.xml 关键节点 ===========================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.toptoolbar">
<application
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
=========================== Manifest 结束 ===========================
*/
/*
=========================== res/values/styles.xml ===========================
<resources>
<!-- 应用主题:隐藏原生 ActionBar -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<!-- 指定 Toolbar 默认样式 -->
<item name="toolbarStyle">@style/MyToolbarStyle</item>
</style>
<!-- Toolbar 样式 -->
<style name="MyToolbarStyle" parent="">
<item name="android:background">?attr/colorPrimary</item>
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="titleTextAppearance">@style/Toolbar.TitleText</item>
<item name="subtitleTextAppearance">@style/Toolbar.SubtitleText</item>
<item name="android:theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
<style name="Toolbar.TitleText">
<item name="android:textColor">@android:color/white</item>
<item name="android:textSize">20sp</item>
</style>
<style name="Toolbar.SubtitleText">
<item name="android:textColor">#FFDDDDDD</item>
<item name="android:textSize">14sp</item>
</style>
</resources>
=========================== styles.xml 结束 ===========================
*/
/*
=========================== res/layout/activity_main.xml ===========================
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 1. 顶部导航栏 -->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:logo="@mipmap/ic_launcher_round" <!-- Logo -->
app:title="@string/app_name" <!-- 标题 -->
app:subtitle="首页" <!-- 子标题 -->
app:navigationIcon="@drawable/ic_back" <!-- 导航图标 -->
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<!-- 2. 主内容区域 -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="这里是应用主内容"
android:gravity="center"
android:textSize="18sp"/>
</LinearLayout>
=========================== layout 结束 ===========================
*/
/*
=========================== res/menu/main_menu.xml ===========================
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:title="搜索"
android:icon="@android:drawable/ic_menu_search"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_settings"
android:title="设置"
android:icon="@android:drawable/ic_menu_manage"
app:showAsAction="never"/>
</menu>
=========================== menu 结束 ===========================
*/
/*
=========================== res/drawable/ic_back.xml ===========================
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
=========================== drawable 结束 ===========================
*/
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 绑定布局
setContentView(R.layout.activity_main);
// 1. 获取 Toolbar,替代 ActionBar
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// 2. 处理导航按钮(通常是“向上”或“返回”)
toolbar.setNavigationOnClickListener(v -> {
// 默认行为:结束当前 Activity
finish();
});
// 3. 可在代码里动态修改标题、Logo
// toolbar.setTitle("首页");
// toolbar.setLogo(R.drawable.ic_app_logo);
}
// 4. 创建菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
// 5. 处理菜单点击
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search:
Toast.makeText(this, "点击了搜索", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_settings:
Toast.makeText(this, "点击了设置", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
五、方法解读
-
主题与样式
-
在
AppTheme
中关闭原生ActionBar
,通过toolbarStyle
指定MyToolbarStyle
; -
MyToolbarStyle
设置背景色、最小高度、标题与溢出菜单主题。
-
-
布局定义
-
在
activity_main.xml
顶部声明<Toolbar>
,使用app:logo
、app:title
、app:subtitle
、app:navigationIcon
等属性; -
app:popupTheme
控制溢出菜单的主题样式(若要浅底深色文字或反之)。
-
-
Activity 中绑定
-
setSupportActionBar(toolbar)
将Toolbar
作为ActionBar
; -
toolbar.setNavigationOnClickListener()
处理导航图标点击(通常是返回或抽屉菜单切换);
-
-
菜单加载与处理
-
onCreateOptionsMenu()
中通过getMenuInflater().inflate()
加载res/menu/main_menu.xml
; -
onOptionsItemSelected()
根据item.getItemId()
执行相应逻辑。
-
-
动态修改
-
可在运行时调用
toolbar.setTitle()
、toolbar.setLogo()
、toolbar.getMenu().findItem(...).setVisible()
等方法动态更新。
-
-
自定义扩展
-
若要在
Toolbar
中嵌入搜索框,可在布局中<include layout="@layout/toolbar_search"/>
,或使用toolbar.addView()
; -
与
TabLayout
结合,可将TabLayout
放入AppBarLayout
,实现顶部 Tab 导航。
-
六、项目总结
-
核心优势
-
使用
Toolbar
替代ActionBar
,灵活可自定义; -
主题配置与样式分离,易于全局修改;
-
XML + 代码结合,可动态控制标题、Logo、菜单;
-
与 Material 组件无缝集成(
AppBarLayout
、CollapsingToolbarLayout
、TabLayout
)。
-
-
可扩展方向
-
将
Toolbar
包装成自定义控件TopBar
,支持更多自定义 Attribute; -
在
AppBarLayout
中使用CoordinatorLayout
实现滑动隐藏/固定效果; -
在
CollapsingToolbarLayout
中结合大图折叠动画; -
与
DrawerLayout
配合,实现抽屉菜单按钮及侧滑导航。
-
-
注意事项
-
确保在
styles.xml
中使用Theme.AppCompat.Light.NoActionBar
或设置windowNoTitle
、windowActionBar
; -
图标使用
VectorDrawable
并在build.gradle
中启用vectorDrawables.useSupportLibrary true
; -
popupTheme
要与主背景色形成对比,保证菜单文字可见。
-