Android实现顶部导航栏(附带源码)

一、项目介绍

在现代 Android 应用中,顶部导航栏(通常指 ToolbarAppBarLayout)承担着显示页面标题、导航按钮和操作菜单的职责。一个优秀的顶部导航栏应当具备:

  1. 品牌识别:显示应用 Logo 或标题;

  2. 导航返回:支持“向上”或“返回”按钮;

  3. 操作入口:在右侧提供关键操作(搜索、更多菜单、切换视图);

  4. 风格统一:与应用主题完美融合;

  5. 可扩展:可在布局中或代码里动态更换标题、菜单、Logo。

本教程演示在 AndroidX/AppCompat 环境下,如何从零搭建一个功能完备的顶部导航栏,涵盖:

  • 使用 Toolbar 代替原生 ActionBar

  • 在 XML 中声明与配置;

  • Activity 中通过 setSupportActionBar() 绑定并处理菜单、导航点击;

  • 自定义 Toolbar 布局(添加搜索框、TabLayout 等);

  • 主题与样式配置以适配深色/浅色模式;

  • 演示集成到单一 MainActivity.java 文件中的所有资源。


二、相关技术与知识

  1. AppCompat Toolbar

    • androidx.appcompat.widget.Toolbar:支持自定义视图、菜单、Logo、导航图标;

  2. Menu 与 MenuItem

    • res/menu/ 下定义 <menu>,通过 onCreateOptionsMenu() 加载;

    • 使用 onOptionsItemSelected() 处理点击事件;

  3. 主题与样式

    • styles.xml 中使用 ThemeOverlay.AppCompat.Dark.ActionBar 或自定义 toolbarStyle

    • 通过 android:popupTheme 指定溢出菜单的样式;

  4. 导航图标

    • toolbar.setNavigationIcon() 或在 XML 中 app:navigationIcon="@drawable/ic_back"

    • 通过 toolbar.setNavigationOnClickListener() 处理返回逻辑。

  5. 自定义布局

    • toolbar.inflateMenu()toolbar.addView() 或在 XML 内嵌自定义布局;

    • 可结合 TabLayoutSearchView 实现更丰富的导航栏。

  6. 兼容与性能

    • AppCompat 库确保在 Android 4.1+ 上支持 Toolbar

    • 使用矢量图(VectorDrawable)节省资源。


三、实现思路

  1. 主题配置

    • styles.xml 定义应用主题 AppTheme,设置 windowActionBar=falsewindowNoTitle=true

    • 定义 Toolbar 样式 MyToolbarStyle,包括背景色、标题文本外观、溢出菜单主题;

  2. 布局

    • activity_main.xml 中使用 LinearLayoutCoordinatorLayout,将 Toolbar 放在最上方,下面放置主内容;

    • Toolbar 中通过 XML 属性指定 app:logoapp:titleapp:subtitleapp:navigationIcon

  3. 菜单资源

    • res/menu/main_menu.xml 中定义若干 <item>,指定 android:iconandroid:titleapp:showAsAction="ifRoom"

  4. Activity 绑定

    • MainActivity.onCreate() 中调用 setSupportActionBar(toolbar)

    • onCreateOptionsMenu() 中加载菜单;

    • onOptionsItemSelected() 中处理菜单与导航点击;

  5. 扩展:自定义布局

    • 演示如何在 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);
        }
    }
}

五、方法解读

  1. 主题与样式

    • AppTheme 中关闭原生 ActionBar,通过 toolbarStyle 指定 MyToolbarStyle

    • MyToolbarStyle 设置背景色、最小高度、标题与溢出菜单主题。

  2. 布局定义

    • activity_main.xml 顶部声明 <Toolbar>,使用 app:logoapp:titleapp:subtitleapp:navigationIcon 等属性;

    • app:popupTheme 控制溢出菜单的主题样式(若要浅底深色文字或反之)。

  3. Activity 中绑定

    • setSupportActionBar(toolbar)Toolbar 作为 ActionBar

    • toolbar.setNavigationOnClickListener() 处理导航图标点击(通常是返回或抽屉菜单切换);

  4. 菜单加载与处理

    • onCreateOptionsMenu() 中通过 getMenuInflater().inflate() 加载 res/menu/main_menu.xml

    • onOptionsItemSelected() 根据 item.getItemId() 执行相应逻辑。

  5. 动态修改

    • 可在运行时调用 toolbar.setTitle()toolbar.setLogo()toolbar.getMenu().findItem(...).setVisible() 等方法动态更新。

  6. 自定义扩展

    • 若要在 Toolbar 中嵌入搜索框,可在布局中 <include layout="@layout/toolbar_search"/>,或使用 toolbar.addView()

    • TabLayout 结合,可将 TabLayout 放入 AppBarLayout,实现顶部 Tab 导航。


六、项目总结

  • 核心优势

    1. 使用 Toolbar 替代 ActionBar,灵活可自定义;

    2. 主题配置与样式分离,易于全局修改;

    3. XML + 代码结合,可动态控制标题、Logo、菜单;

    4. 与 Material 组件无缝集成(AppBarLayoutCollapsingToolbarLayoutTabLayout)。

  • 可扩展方向

    1. Toolbar 包装成自定义控件 TopBar,支持更多自定义 Attribute;

    2. AppBarLayout 中使用 CoordinatorLayout 实现滑动隐藏/固定效果;

    3. CollapsingToolbarLayout 中结合大图折叠动画;

    4. DrawerLayout 配合,实现抽屉菜单按钮及侧滑导航。

  • 注意事项

    • 确保在 styles.xml 中使用 Theme.AppCompat.Light.NoActionBar 或设置 windowNoTitlewindowActionBar

    • 图标使用 VectorDrawable 并在 build.gradle 中启用 vectorDrawables.useSupportLibrary true

    • popupTheme 要与主背景色形成对比,保证菜单文字可见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值