Android ToolBar 实现高仿 QQ 消息与电话

发布时间:2026/9/23 12:45:33

Android ToolBar 实现高仿 QQ 消息与电话
一、引言与项目背景在日常 Android 开发中QQ 作为一款国民级社交应用其顶部导航栏设计简洁高效是很多开发者学习的标杆。QQ 的消息与电话界面顶部 ToolBar 不仅展示了标题、状态、联系人信息还集成了视频通话、语音通话、搜索、更多菜单等丰富的交互元素。本文将从零开始手把手带你使用 Android 原生 ToolBar 组件实现一个高仿 QQ 消息与电话界面的完整功能涵盖 UI 布局、自定义 View、动画交互、状态管理、主题适配等核心知识点全文超过 2 万字适合中级及以上 Android 开发者深入阅读。二、ToolBar 基础与环境搭建2.1 ToolBar 与 ActionBar 的关系在 Android 5.0API 21之前应用顶部导航主要使用 ActionBar。ActionBar 功能有限定制性差难以满足复杂 UI 需求。Android 5.0 引入了 ToolBar 组件它本质上是一个 ViewGroup可以像普通 View 一样嵌入到布局文件中支持高度自定义。ToolBar 与 ActionBar 的最大区别在于ToolBar 是 Material Design 体系下的通用组件不强制绑定 Activity 的窗口装饰开发者可以自由添加子 View、自定义样式、控制动画表现。同时ToolBar 天然支持与 CoordinatorLayout、AppBarLayout 等 Material 组件协同工作可以轻松实现折叠、上滑隐藏等高级效果而 ActionBar 几乎无法做到。2.2 引入 Material Design 依赖要使用 ToolBar首先需要在项目中引入 Material Design 库。在 app 模块的 build.gradle 中添加以下依赖dependencies { implementation com.google.android.material:material:1.9.0 implementation androidx.appcompat:appcompat:1.6.1 implementation androidx.core:core-ktx:1.10.1 implementation androidx.constraintlayout:constraintlayout:2.1.4 }确保使用 AndroidX 系列包旧版 support 库已停止维护。ToolBar 类位于 androidx.appcompat.widget.Toolbar 包中。如果项目仍在使用 support 库建议尽快迁移到 AndroidX因为 Google 已停止对 support 库的功能更新和安全维护。2.3 基础 ToolBar 布局文件在 activity_main.xml 中编写一个最基础的 ToolBar 布局?xml version1.0 encodingutf-8? LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:apphttp://schemas.android.com/apk/res-auto android:layout_widthmatch_parent android:layout_heightmatch_parent android:orientationvertical androidx.appcompat.widget.Toolbar android:idid/toolbar android:layout_widthmatch_parent android:layout_height?attr/actionBarSize android:backgroundcolor/colorPrimary android:elevation4dp android:themestyle/ThemeOverlay.AppCompat.Dark.ActionBar app:popupThemestyle/ThemeOverlay.AppCompat.Light app:titleTextColorandroid:color/white / FrameLayout android:idid/content_frame android:layout_widthmatch_parent android:layout_heightmatch_parent / /LinearLayout在 Activity 中使用 ToolBar 替代默认 ActionBarpublic class MainActivity extends AppCompatActivity { private Toolbar toolbar; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar findViewById(R.id.toolbar); setSupportActionBar(toolbar); // 可选配置 if (getSupportActionBar() ! null) { getSupportActionBar().setDisplayHomeAsUpEnabled(false); getSupportActionBar().setDisplayShowTitleEnabled(false); } } }由于本文最终要实现高仿 QQ 风格因此我们将默认隐藏 ToolBar 自带的标题和返回键转而使用自定义布局来承载头像、昵称、状态等复杂 UI。2.4 自定义 ToolBar 主题在 styles.xml 中定义 ToolBar 专用主题覆盖标题颜色、字体大小、溢出菜单样式等属性style nameAppTheme.Toolbar parentThemeOverlay.AppCompat.Dark.ActionBar item nameandroid:textColorPrimaryandroid:color/white/item item nameandroid:textColorSecondaryandroid:color/white/item item nameactionMenuTextColorandroid:color/white/item item nametitleTextStylestyle/ToolbarTitleStyle/item /style style nameToolbarTitleStyle item nameandroid:textSize18sp/item item nameandroid:textColorandroid:color/white/item item nameandroid:fontFamilysans-serif-medium/item /style在 app 的全局主题中将 ToolBar 的默认样式替换为上面定义的主题可以保证所有 ToolBar 实例都拥有一致的外观表现。三、高仿 QQ 消息顶部布局实战3.1 分析 QQ 消息界面顶部结构打开 QQ 的消息列表页面我们观察到顶部导航栏的结构从上到下依次为顶部状态栏区域系统状态栏、信号、电量等不属于 ToolBar 本体、标题栏区域左侧显示用户头像加昵称中间显示“消息”或自定义状态文字右侧通常为添加联系人、搜索等图标。在一些版本中中间会显示“消息”二字右侧依次为“”和搜索图标。需要注意的是QQ 的消息页 ToolBar 并不是简单地使用 ToolBar 的 title 和 menu而是采用完全自定义布局的方式。具体做法是在 ToolBar 内部嵌套一个 LinearLayout 或 ConstraintLayout再放置头像 ImageView、昵称 TextView、状态 TextView 以及若干功能图标。这种设计可以让整个标题栏的排版自由度达到最高便于后期修改与扩展。同时QQ 的电话页顶部结构类似但中间区域会显示“电话”或在线状态右侧图标变为通话记录、添加联系人等。本文将分别实现消息页和电话页的 ToolBar并通过 ViewPager 或 TabLayout 实现页签切换。3.2 消息页 ToolBar 自定义布局实现首先创建消息页的 ToolBar 布局文件 layout_toolbar_message.xmlandroidx.appcompat.widget.Toolbar xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:apphttp://schemas.android.com/apk/res-auto android:idid/toolbar_message android:layout_widthmatch_parent android:layout_height?attr/actionBarSize android:backgroundcolor/qq_blue android:elevation4dp LinearLayout android:layout_widthmatch_parent android:layout_heightmatch_parent android:gravitycenter_vertical android:orientationhorizontal de.hdodenhof.circleimageview.CircleImageView android:idid/iv_avatar android:layout_width36dp android:layout_height36dp android:layout_marginStart8dp android:srcdrawable/ic_avatar_default / TextView android:idid/tv_nickname android:layout_width0dp android:layout_heightwrap_content android:layout_marginStart10dp android:layout_weight1 android:ellipsizeend android:maxLines1 android:text我的昵称 android:textColorandroid:color/white android:textSize16sp android:textStylebold / TextView android:idid/tv_status android:layout_widthwrap_content android:layout_heightwrap_content android:layout_marginEnd8dp android:text在线 android:textColorcolor/qq_status_green android:textSize12sp / ImageView android:idid/iv_add android:layout_width24dp android:layout_height24dp android:layout_marginEnd12dp android:srcdrawable/ic_add / ImageView android:idid/iv_search android:layout_width24dp android:layout_height24dp android:layout_marginEnd12dp android:srcdrawable/ic_search / /LinearLayout /androidx.appcompat.widget.Toolbar上述布局使用了 CircleImageView 来实现圆形头像需要依赖implementation de.hdodenhof:circleimageview:3.1.0在 Activity 或 Fragment 中通过下面的方式加载并设置自定义布局Toolbar toolbar findViewById(R.id.toolbar_message); toolbar.setTitle(); // 隐藏默认标题 toolbar.setContentInsetsAbsolute(0, 0); // 清除内边距 // 设置自定义内容 toolbar.addView(getLayoutInflater().inflate(R.layout.layout_toolbar_message, toolbar, false)); // 或者使用 ViewStub 延迟加载以优化性能注意为了完全掌控布局我们清除了 ToolBar 的默认左右内边距否则无法贴边显示头像等内容。同时自定义的 LinearLayout 已经承担了所有内容摆放任务因此不需要再调用 setSupportActionBar 中的标题相关方法。3.3 消息页 ToolBar 交互事件处理为每个按钮绑定点击事件并在代码中处理逻辑ImageView ivAdd toolbar.findViewById(R.id.iv_add); ivAdd.setOnClickListener(v - { // 弹出添加好友、创建群聊等菜单 showAddMenu(v); }); ImageView ivSearch toolbar.findViewById(R.id.iv_search); ivSearch.setOnClickListener(v - { // 跳转到搜索页面或展开搜索栏 navigateToSearch(); }); CircleImageView ivAvatar toolbar.findViewById(R.id.iv_avatar); ivAvatar.setOnClickListener(v - { // 跳转到个人主页或侧边栏 navigateToProfile(); });对于昵称点击可以展示在线状态切换或跳转到设置页面。这些交互可以根据实际需求灵活调整。3.4 搜索展开与更多菜单实现当用户点击搜索图标时我们可以在 ToolBar 内部动态切换为搜索输入框覆盖原有布局实现类似 QQ 的沉浸式搜索效果。实现思路如下布局切换在 ToolBar 内部预先放置两个 FrameLayout其中一个承载默认内容另一个承载搜索栏通过设置 visibility 切换。动画过渡使用 TransitionManager 或自定义动画让搜索栏展开/收缩时更加平滑。键盘控制展开搜索栏时自动弹出软键盘并监听返回键以折叠搜索栏。FrameLayout android:idid/fl_search_container android:layout_widthmatch_parent android:layout_heightmatch_parent android:visibilitygone EditText android:idid/et_search android:layout_widthmatch_parent android:layout_heightmatch_parent android:backgroundandroid:color/transparent android:hint搜索 android:textColorHint#80ffffff android:textColorandroid:color/white android:inputTypetext / ImageView android:idid/iv_close_search android:layout_width24dp android:layout_height24dp android:layout_gravityend|center_vertical android:layout_marginEnd12dp android:srcdrawable/ic_close / /FrameLayout在代码中通过设置 fl_search_container 可见并隐藏默认 LinearLayout实现搜索模式切换。同时处理返回键逻辑在搜索可见时优先折叠搜索栏而非退出页面。四、高仿 QQ 电话顶部布局实战4.1 电话页 ToolBar 结构分析QQ 的电话页通常与消息页并排通过底部导航或顶部 Tab 切换。电话页的 ToolBar 布局类似但中间显示“电话”二字右侧依次为通话记录图标和添加联系人图标。有些版本中还会在标题下方显示“在线”或“可使用 QQ 电话”等提示信息。电话页 ToolBar 同样使用完全自定义布局不再重复基础搭建直接给出核心布局文件和交互实现。4.2 电话页 ToolBar 布局实现LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightmatch_parent android:gravitycenter_vertical android:orientationhorizontal TextView android:idid/tv_title_call android:layout_width0dp android:layout_heightwrap_content android:layout_weight1 android:gravitycenter android:text电话 android:textColorandroid:color/white android:textSize18sp android:textStylebold / ImageView android:idid/iv_call_history android:layout_width24dp android:layout_height24dp android:layout_marginEnd12dp android:srcdrawable/ic_history / ImageView android:idid/iv_add_contact android:layout_width24dp android:layout_height24dp android:layout_marginEnd12dp android:srcdrawable/ic_add_contact / /LinearLayout将该布局 inflate 到电话页的 ToolBar 中即可。交互逻辑类似点击通话记录打开最近通话列表点击添加联系人跳转到联系人选择界面。4.3 电话页状态指示器有时需要在电话页顶部展示一个细条状态栏比如“网络状态良好”或者“正在通话中”。这可以通过在 ToolBar 下方添加一个狭长的 View 或者直接在 ToolBar 内部增加一个窄条布局来实现。例如View android:idid/view_status_bar android:layout_widthmatch_parent android:layout_height4dp android:backgroundcolor/qq_green /在代码中根据网络状态或通话状态动态改变背景颜色和显示隐藏增加用户体验。五、下拉搜索框与更多菜单实现5.1 弹出式更多菜单除了在 ToolBar 右侧直接放置图标外QQ 还常使用弹出菜单PopupMenu来收纳更多操作。例如点击“”按钮弹出包含“加好友/群”、“扫一扫”、“面对面快传”等的菜单列表。使用 PopupMenu 实现private void showAddMenu(View anchor) { PopupMenu popup new PopupMenu(this, anchor, Gravity.END); popup.getMenuInflater().inflate(R.menu.menu_add, popup.getMenu()); popup.setOnMenuItemClickListener(item - { int id item.getItemId(); if (id R.id.action_add_friend) { // 跳转加好友 return true; } else if (id R.id.action_create_group) { // 跳转建群 return true; } return false; }); popup.show(); }菜单文件 res/menu/menu_add.xmlmenu xmlns:androidhttp://schemas.android.com/apk/res/android item android:idid/action_add_friend android:title加好友/群 / item android:idid/action_create_group android:title创建群聊 / item android:idid/action_scan android:title扫一扫 / /menu5.2 下拉搜索框的完整实现前文已经描述了搜索栏的基本布局切换这里补充输入事件处理和搜索历史管理。当用户在搜索框输入文字时可以使用 RxJava 或 LiveData 实现防抖避免频繁触发搜索请求。同时可以保存搜索历史并在搜索栏下方展示通过 RecycleView 实现历史记录列表。代码示例private void setupSearchInput(EditText etSearch) { RxTextView.textChanges(etSearch) .debounce(300, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::performSearch); }搜索框展开时toolbar 下方的 RecyclerView 可以动态显示搜索结果或历史记录。为了不遮挡内容区域通常会用 FrameLayout 承载主内容将搜索建议列表覆盖在内容之上。六、动画与交互优化6.1 ToolBar 展开与收缩动画借助 AppBarLayout 和 CoordinatorLayout可以实现 ToolBar 跟随列表滑动收起和展开的效果。但 QQ 的消息页 ToolBar 并不支持滑动折叠而是始终固定。本文主要介绍点击搜索时搜索栏的展开动画以及 Tab 切换时 ToolBar 内容的平滑过渡。使用 TransitionManager 简化动画TransitionManager.beginDelayedTransition(toolbar, new Fade()); toolbar.removeAllViews(); toolbar.addView(searchView);6.2 Tab 切换时 ToolBar 平滑切换QQ 消息页和电话页共用同一个 ToolBar 还是分别维护通常可以使用 ViewPager 配合 TabLayoutToolBar 独立于 ViewPager 之外根据当前选中的页面动态切换 ToolBar 的内容。例如viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { Override public void onPageSelected(int position) { switchToolbarContent(position); } });switchToolbarContent 方法内部移除当前 ToolBar 的内容并 inflate 对应的布局文件。为了增加平滑过渡可以使用 android:animateLayoutChangestrue 在 ToolBar 上启用默认布局动画或者自定义内容淡入淡出效果。6.3 图标点击涟漪效果为所有图标 ImageView 设置 background 为 ripple 效果提升触摸反馈。可以使用 ?attr/selectableItemBackgroundBorderless 或自定义 ripple。android:background?attr/selectableItemBackgroundBorderless七、主题适配与多机型兼容7.1 日间/夜间模式适配QQ 支持夜间模式ToolBar 的背景、文字颜色、图标颜色都需要随之变化。利用 Android 的资源限定符和主题属性可以方便地实现。定义 attrs.xmlattr nametoolbarBackground formatcolor / attr nametoolbarTextColor formatcolor /然后在日间和夜间主题中分别赋值ToolBar 布局中使用 ?attr/toolbarBackground 等引用属性即可。图标可以使用 tint 属性动态着色。7.2 刘海屏、挖孔屏适配在全面屏时代ToolBar 的高度和内容布局需要考虑状态栏高度以及刘海区域。可以通过设置 android:fitsSystemWindowstrue 并配合 WindowInsets 来获取系统安全区域手动调整 ToolBar 的 padding 或 margin。toolbar.setOnApplyWindowInsetsListener((v, insets) - { int top insets.getSystemWindowInsetTop(); v.setPadding(v.getPaddingLeft(), top, v.getPaddingRight(), v.getPaddingBottom()); return insets.consumeSystemWindowInsets(); });7.3 多屏幕尺寸适配针对不同屏幕宽度头像大小、图标间距、文字大小可以使用 dimens.xml 中不同限定符的值。对于大屏设备可以适当增大头像和图标尺寸保持视觉协调。八、性能优化与最佳实践8.1 避免过度绘制自定义 ToolBar 内部 View 层级应尽量扁平化避免嵌套过多的布局容器。使用 ConstraintLayout 替代多层 LinearLayout 可以有效减少层级。此外为 ToolBar 设置背景色时不要覆盖不必要的透明区域。8.2 延迟加载与 ViewStub如果 ToolBar 中包含不常用或复杂的子布局如搜索栏、更多菜单可以使用 ViewStub 延迟初始化减少首次绘制时间。ViewStub android:idid/stub_search android:layoutlayout/layout_search_bar android:layout_widthmatch_parent android:layout_heightmatch_parent /仅在需要展开搜索时调用 inflate之后再进行切换。8.3 内存与线程管理在处理图标资源时使用矢量图VectorDrawable以减小 APK 体积并适应不同分辨率。避免在 ToolBar 的频繁刷新过程中创建大量临时对象。对于搜索界面的历史记录 Adapter使用 DiffUtil 高效更新列表。8.4 无障碍与国际化为所有图标添加 contentDescription 属性以支持无障碍服务。文字内容不要硬编码使用 strings.xml 资源便于后期国际化。九、总结与展望本文从 ToolBar 基础开始逐步深入到高仿 QQ 消息与电话界面的完整实现涵盖了自定义布局、搜索展开、主题适配、动画交互、性能优化等多个方面。通过掌握这些技术读者不仅可以实现一个高仿 QQ 风格的应用顶部导航还能举一反三打造出各种复杂自定义 UI。未来随着 Jetpack Compose 的普及ToolBar 的使用方式可能会逐渐被 TopAppBar 和自定义 Composable 替代但本文涉及的自定义布局思想、状态管理、动画处理等能力在任何 UI 框架下都是通用的底层能力。建议读者在理解原生 View 体系的基础上再去学习 Compose会事半功倍。完整项目源码可访问实际开发中可提供 GitHub 链接希望本文能帮助你的项目快速落地 QQ 风格的顶部导航栏。

相关新闻

Android关于SDK版本不兼容解决方案

Android关于SDK版本不兼容解决方案

2026/9/23 12:45:23

一、引言Android生态从2008年发布至今已经历了十余个大版本的迭代,每个版本都带来了新的API、新的特性和新的限制。对于Android开发者而言,"版本兼容"从来不是一个可以回避的话题,而是贯穿项目始终的核心工程问题。无论是新项目从零…

等价类覆盖属于黑盒测试方法,不依赖程序内部结构,而是基于输入域的划分

等价类覆盖属于黑盒测试方法,不依赖程序内部结构,而是基于输入域的划分

2026/8/23 0:14:04

等价类覆盖属于黑盒测试方法,不依赖程序内部结构,而是基于输入域的划分;而白盒测试覆盖标准均以程序内部逻辑结构(如代码语句、分支、路径等)为基础。选项A(语句覆盖)、C(判定覆盖&a…

Haskell 是一种纯函数式程序设计语言,强调不可变数据、无副作用的函数、高阶函数、惰性求值和代数数据类型等核心特性

Haskell 是一种纯函数式程序设计语言,强调不可变数据、无副作用的函数、高阶函数、惰性求值和代数数据类型等核心特性

2026/8/23 10:39:43

Haskell 是一种纯函数式程序设计语言,强调不可变数据、无副作用的函数、高阶函数、惰性求值和代数数据类型等核心特性。它不依赖变量赋值或状态变更,而是通过函数组合与递归表达计算逻辑。相比之下: C 是典型的**过程式(命令式&am…

CANN/GE ACL数据集缓冲区添加函数

CANN/GE ACL数据集缓冲区添加函数

2026/9/21 18:38:46

aclmdlAddDatasetBuffer 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Te…

用ffmpeg高效批量调整图片尺寸的实战指南

用ffmpeg高效批量调整图片尺寸的实战指南

2026/9/21 18:41:09

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

2026/9/21 18:36:40

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and mu…

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

2026/9/21 18:37:26

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system sup…

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

2026/9/21 18:40:29

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

2026/9/21 18:36:17

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting mi…

远程协作的工作台整理

远程协作的工作台整理

2026/9/22 0:19:28

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/21 23:38:13

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/22 0:48:53

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…