news 2026/9/21 16:21:03

Material Components for Android 搜索组件实战:SearchBar 与 SearchView 完整开发指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Material Components for Android 搜索组件实战:SearchBar 与 SearchView 完整开发指南
  • UI组件
  • 移动开发
  • 设计系统

【免费下载链接】material-components-android

[MAINTENANCE MODE] Modular and customizable Material Design UI components for Android

项目地址:https://gitcode.com/gh_mirrors/ma/material-components-android
点击查看免费下载

本指南以仓库文档 docs/components/Search.md 为核心,结合com.google.android.material.search包下的真实源码与 Catalog 示例,系统讲解 Material 3 Search 组件(SearchBarSearchView)的结构、属性、M3 Expressive 新特性、代码集成与滚动行为定制。读完本文,你将能够在一个 Android 应用中完整落地「搜索栏 + 全屏搜索视图」的组合体验,并掌握包含式动画、预测性返回、无障碍支持等进阶配置。

一、什么是 Search 组件

Search(搜索)是一种导航模式,允许用户在应用中快速查找信息:用户在搜索栏(search bar)或搜索视图(search view)的文本框中输入查询,随后看到相关结果。Material Components for Android 将这一模式封装为两个协同工作的组件:

  1. SearchBar:位于屏幕顶部的常驻、醒目的搜索输入区域,用于承载搜索入口。
  2. SearchView:全屏模态界面,通常由点击搜索图标或SearchBar触发打开,用于输入查询、展示历史/建议/结果。

从源码结构看,这两个组件都位于 lib/java/com/google/android/material/search 包内,核心实现为SearchBar.javapublic class SearchBar extends Toolbar,见 SearchBar.java)与SearchView.javapublic class SearchView extends FrameLayout implements CoordinatorLayout.AttachedBehavior, MaterialBackHandler,见 SearchView.java),动画逻辑由 SearchBarAnimationHelper.java 和 SearchViewAnimationHelper.java 承载。

二、组件解剖(Anatomy)

SearchBar 结构

SearchBar由以下部分组成:

  1. Container(容器)
  2. Leading icon button(前导图标按钮,默认为放大镜)
  3. Supporting text(辅助文本,即 hint 提示)
  4. Avatar 或 trailing icon(尾部头像或图标,可选)

SearchView 结构

SearchView由以下部分组成:

  1. Container(容器)
  2. Header(头部区域)
  3. Leading icon button(前导图标按钮,默认为返回箭头)
  4. Supporting text(辅助文本)
  5. Trailing icon button(尾部图标按钮,含清除按钮)
  6. Input text(输入文本EditText
  7. Divider(分隔线)

SearchView在源码中通过 mtrl_search_view.xml 布局将这些元素组装起来,并在构造函数中逐一绑定(scrimrootViewtoolbareditTextclearButtondivider等,见 SearchView.java)。注意SearchView重写了addView,所有以 XML 或代码方式添加的子 View 都会被放入内容容器contentContainer,这也是它能够内嵌搜索建议、结果列表的原因。

三、添加依赖与版本要求

Material Search 组件在1.8.0版本引入,使用前需确保依赖com.google.android.material:material:1.8.0或更高版本。完整的环境搭建步骤(Gradle 依赖、主题继承等)见仓库的 docs/getting-started.md。

四、M3 Expressive 更新(1.13.0+ 风格)

M3 Expressive 为搜索组件带来了一批外观与行为更新,仓库中的主题样式定义于 lib/java/com/google/android/material/search/res/values/styles.xml。

SearchBar 更新

  • 新增 Centered Search Text 属性:支持文本居中显示。
  • 新增 Maximum Width:限制搜索栏最大宽度。
  • 新增 Lift on Scroll Color 属性:滚动抬升时的颜色。
  • Padding 与 inset 更新:边距与系统栏内边距调整。

SearchBar的默认样式为:

<item name="materialSearchBarStyle">@style/Widget.Material3Expressive.SearchBar</item>

也可以显式使用居中文本样式:

<item name="materialSearchBarStyle">@style/Widget.Material3Expressive.SearchBar.CenteredText</item>

推荐布局:SearchBar 放入 AppBarLayout

Expressive 阶段推荐的展示方式是让SearchBar位于AppBarLayout内部,构成 "AppBar with Search"。你只需在AppBarLayout上指定主题:

<item name="materialSearchViewStyle">@style/Widget.Material3Expressive.SearchView.AppBarWithSearch</item>

同时在AppBarLayout上应用android:theme="ThemeOverlay.Material3Expressive.AppBarWithSearch",即可自动为AppBarLayoutSearchBar设置样式。该主题覆盖层下SearchBar的默认样式为居中文本配置;若想使用起始对齐文本,需在SearchBar上显式设置@style/Widget.Material3Expressive.SearchBar.AppBarWithSearch

SearchBar 与 MaterialToolbar 搭配(迁移路径)

新的 AppBar with Search 配置把图标从SearchBar内部移到了AppBarLayout中,客户端需要自己添加MaterialButton来替代这些图标。对于存量代码,官方提供了一条更平滑的迁移路径:SearchBar包进MaterialToolbar,将前导/尾部图标设置到MaterialToolbar,输入方式保持不变。示例:

<com.google.android.material.appbar.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" app:materialThemeOverlay="@style/ThemeOverlay.Material3Expressive.AppBarWithSearch" app:statusBarForeground="?attr/colorSurface"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" app:navigationIcon="@drawable/ic_home_checkable_24px" app:layout_scrollFlags="enterAlways|scroll|snap" app:navigationContentDescription="@string/home_icon_description" app:menu="@menu/search_menu"> <com.google.android.material.search.SearchBar android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:hint="@string/searchbar_hint"> </com.google.android.material.search.SearchBar> </com.google.android.material.appbar.MaterialToolbar> </com.google.android.material.appbar.AppBarLayout>

包含式(Contained)SearchView 样式

SearchBar按上述方式位于AppBarLayout内时,可启用新的包含式SearchView样式——SearchBar在展开动画中会视觉上持续存在于SearchView内部,形成更连贯、更具表现力的体验。在主题中同时设置materialSearchViewStyle即可开启:

<item name="materialSearchViewStyle">@style/Widget.Material3Expressive.SearchView.AppBarWithSearch</item>

注意:包含式SearchView的 "bouncy"(弹性)动画只在 Expressive 主题(如Theme.Material3Expressive.*)下可用;基础 M3 主题(Theme.Material3.*)虽然支持包含式视觉样式,但SearchBar展开会退化为线性运动。

SearchBar 图标动画

包含式展开过程中,SearchBar的兄弟视图(如图标按钮)会被动画移出屏幕以腾出空间:

  • SearchBarToolbar的直接子 View,导航按钮与菜单操作视图会自动被当作兄弟视图处理。

  • 其他场景需显式声明兄弟视图,可通过 XML 属性:

    • app:startSiblingViewId
    • app:endSiblingViewId

    或编程式 API:

    • SearchBar#setStartSiblingViewId(id)
    • SearchBar#setEndSiblingViewId(id)

    注意每侧只能指定一个 ID;如需同时动画多个图标,请将它们包裹进同一个ViewGroup(如LinearLayout),再传入该容器的 ID。对应属性在 attrs.xml 中声明。

五、关键属性(Key Properties)

SearchBar 属性

元素属性相关方法默认值
最大宽度android:maxWidthsetMaxWidth
getMaxWidth
-1(未设置)
自适应最大宽度开关app:adaptiveMaxWidthEnabled--false
最小高度android:minHeightsetMinHeight
getMinHeight
@dimen/m3_searchbar_height
搜索文本外观android:textAppearancesetTextAppearance
getTextAppearance
@style/TextAppearance.Material3.SearchBar
搜索文本android:textsetText
getText
null
搜索提示android:hintsetHint
getHint
null
搜索文本居中app:textCenteredsetTextCentered
getTextCentered
false
颜色app:backgroundTint--?attr/colorSurfaceContainerHigh
滚动抬升app:liftOnScroll--false
抬升颜色app:liftOnScrollColor--?attr/colorSurfaceContainerHighest
默认边距开关app:defaultMarginsEnabled--true
导航图标开关app:hideNavigationIcon--false
进入 SearchView 时动画移出的起始兄弟视图app:startSiblingViewIdsetStartSiblingViewId
getStartSiblingViewId
-1(未设置)
进入 SearchView 时动画移出的结束兄弟视图app:endSiblingViewIdsetEndSiblingViewId
getEndSiblingViewId
-1(未设置)

除文档中的属性外,从 attrs.xml 的SearchBarstyleable 还可以看到:elevation(阴影高度)、defaultScrollFlagsEnabled(默认 AppBarLayout 滚动标志)、forceDefaultNavigationOnClickListener(强制默认导航点击监听,供将SearchBar设为 ActionBar 时使用)、tintNavigationIcon/navigationIconTint(导航图标着色)、strokeColor/strokeWidth(描边)等。默认高度定义于 dimens.xml:m3_searchbar_height引用m3_comp_search_bar_container_height令牌。

SearchView 属性

元素属性相关方法默认值
搜索文本外观android:textAppearancesetTextAppearance
getTextAppearance
@style/TextAppearance.Material3.SearchBar
搜索文本android:textsetText
getText
null
搜索提示android:hintsetHint
getHint
null
颜色app:backgroundTint--?attr/colorSurfaceContainerHigh
导航图标开关app:hideNavigationIcon--true
DrawerArrowDrawable 开关app:useDrawerArrowDrawable--false
软键盘自动弹出开关app:autoShowKeyboardsetAutoShowKeyboardtrue
分隔线开关app:dividerVisible--true

SearchViewstyleable 还包含searchPrefixText(搜索前缀文本)、animateNavigationIcon/animateMenuItems(是否将导航图标/菜单项从SearchBar动画过渡到SearchView,默认均为true)、headerLayout(头部布局)、backHandlingEnabled(自动返回处理,默认true)、containedAnimationEnabled(包含式展开动画开关,默认false),见 attrs.xml。

样式速查

元素样式主题属性
SearchBar 默认样式Widget.Material3.SearchBar?attr/materialSearchBarStyle
Expressive SearchBar 默认样式Widget.Material3Expressive.SearchBar?attr/materialSearchBarStyle
Expressive SearchBar 居中文本样式Widget.Material3Expressive.SearchBar.CenteredText?attr/materialSearchBarStyle
SearchView 默认样式Widget.Material3.SearchView?attr/materialSearchViewStyle
SearchView Toolbar 样式Widget.Material3.SearchView.Toolbar?attr/materialSearchViewToolbarStyle
SearchView Toolbar 高度@dimen/m3_searchview_height?attr/materialSearchViewToolbarHeight
Expressive SearchView 默认样式Widget.Material3Expressive.SearchView?attr/materialSearchViewStyle
Expressive SearchView Toolbar 样式Widget.Material3Expressive.SearchView.Toolbar?attr/materialSearchViewToolbarStyle
Expressive SearchView 包含式样式Widget.Material3Expressive.SearchView.AppBarWithSearch?attr/materialSearchViewStyle
Expressive SearchView Toolbar 包含式样式Widget.Material3Expressive.SearchView.Toolbar.AppBarWithSearch?attr/materialSearchViewToolbarStyle
Expressive Toolbar 包含式高度@dimen/m3e_searchview_appbarwithsearch_toolbar_height?attr/materialSearchViewToolbarHeight

六、代码实现

1. 添加 SearchBar

SearchBar本质上是继承Toolbar的浮动搜索输入框,因此天然支持导航图标、菜单项以及其他所有ToolbarAPI;同时内置 hintTextView,并支持嵌套一个居中的品牌元素。使用方式:

searchBar.inflateMenu(R.menu.searchbar_menu); searchBar.setOnMenuItemClickListener( menuItem -> { // Handle menuItem click. return true; });

由于SearchBar extends Toolbar(源码见 SearchBar.java),你也可以通过AppCompatActivity#setSupportActionBar将其设为ActionBar,并重写onCreateOptionsMenu填充菜单。但需要注意:若使用默认的放大镜navigationIcon,可能需要设置app:forceDefaultNavigationOnClickListener="true",避免因 Activity 的ActionBar流程把搜索图标当作返回按钮。

限制SearchBar为了在各 App 间提供一致的视觉,不支持通过android:background设置自定义背景。

2. 添加 SearchView

SearchView提供全屏搜索视图,可展示返回导航、搜索提示与文本、菜单项以及搜索建议与结果,并内置一个随输入内容自动显示/隐藏的清除文本按钮。配置菜单:

searchView.inflateMenu(R.menu.search_view_menu); searchView.setOnMenuItemClickListener( menuItem -> { // Handle menuItem click. return true; });

SearchView通过getEditText()暴露主EditText,可以套用所有传统EditTextAPI(setText()addTextChangedListener()等)。下面的例子把搜索文本回填到SearchBar,并在用户按回车结束时隐藏SearchView

searchView .getEditText() .setOnEditorActionListener( (v, actionId, event) -> { searchBar.setText(searchView.getText()); searchView.hide(); return false; });

3. 无障碍(Accessibility)

  • 应通过android:contentDescription属性或setContentDescription方法为SearchBar/SearchView设置内容描述,方便 TalkBack 等屏幕阅读器播报其用途与动作;组件内的文本会自动提供给无障碍服务,通常无需额外标签。
  • SearchView显示时会自动把未嵌套在其中的兄弟视图标记为对无障碍不重要,隐藏时恢复原值。若在SearchView打开期间改动其根视图层级(例如直接移除SearchView),必须先行调用setModalForAccessibility(false)恢复原始无障碍值——因为此时hide()永远不会被调用(源码逻辑见 SearchView.java 及onDetachedFromWindow)。

4. 过渡监听器

若需要在SearchView动画状态切换时获得回调,可通过SearchView#addTransitionListener注册监听:

searchView.addTransitionListener( (searchView, previousState, newState) -> { if (newState == TransitionState.SHOWING) { // Handle search view opened. } });

TransitionState枚举定义于 SearchView.java,包含HIDINGHIDDENSHOWINGSHOWN四种状态;SearchView内部以currentTransitionState跟踪当前状态,并通过isShowing()getCurrentTransitionState()对外暴露。

5. 预测性返回(Predictive Back)

SearchViewSearchBar按上述方式关联后,组件自动支持预测性返回SearchView实现了MaterialBackHandler,见 SearchView.java,通过MaterialBackOrchestrator注册startBackProgress/updateBackProgress/handleBackInvoked回调)。应用侧除预测性返回的通用前置条件外,无需额外集成。通用迁移步骤见 docs/foundations/PredictiveBack.md。

七、自定义行为与场景

1. 展开 / 收起动画

SearchBar+SearchView组合最大的优势是免费获得展开与收起动画:点击SearchBar展开SearchView,返回时收起。如果单独使用SearchView(无SearchBar),则显示/隐藏退化为滑入滑出过渡。

2. 软键盘输入模式

使用SearchBar+SearchView时推荐windowSoftInputModeadjustNothing,原因有二:

  1. adjustResize会在键盘弹出时调整屏幕尺寸,容易造成展开/收起动画的卡顿。SearchView虽然会通过错峰(staggering)调度键盘与动画来缓解,但首选仍是adjustNothing,让键盘立即显示/隐藏。
  2. 搜索场景下重排屏幕通常无益:用户要么继续输入查看更多结果,要么开始滚动——此时SearchView会自动收起键盘以露出更多内容。

SearchView首次渲染时会从Window读取软输入模式;若在运行时动态修改了输入模式,务必同步调用SearchView#setSoftInputMode让组件调整行为。若不想在显示时自动弹出键盘,设置app:autoShowKeyboard="false"即可。

3. 半透明状态栏

SearchBarSearchView均支持半透明状态栏:

  • 防止SearchBar被半透明状态栏遮挡:将其包裹在设置了android:fitsSystemWindows="true"FrameLayout中。
  • 不要SearchView上设置android:fitsSystemWindows。当使用FLAG_TRANSLUCENT_STATUSandroid:windowTranslucentStatus)或FLAG_LAYOUT_NO_LIMITS时,SearchView会自动添加额外的 spacer surface 填充半透明状态栏下方的空间(源码中对应statusBarSpacer字段与 inset 监听逻辑,见 SearchView.java)。

4. 菜单到返回箭头的动画

SearchBarNavigationDrawer搭配使用,可在SearchView上设置app:useDrawerArrowDrawable="true",开启 "hamburger" 菜单到返回箭头的图标动画,动画在SearchView展开/收起时播放(源码中通过DrawerArrowDrawable实现,见 SearchView.java)。

5. 搜索前缀(Search Prefix)

如需在主搜索EditText前显示固定前缀文本,使用app:searchPrefixText属性。例如设置app:searchPrefixText="To:"会在输入框前显示固定标签 "To:"。此模式下通常配合app:hideNavigationIcon="true"隐藏返回按钮以减少杂乱(导航可由 SearchView 外部处理)。

6. 搜索历史、建议与结果

SearchView是 ViewGroup 组件,可以在其内部嵌套内容,例如:

  • 首次展开时的搜索历史
  • 输入过程中的搜索建议
  • 提交搜索后的结果列表
<com.google.android.material.search.SearchView android:layout_width="match_parent" android:layout_height="match_parent" android:hint="@string/searchbar_hint" app:layout_anchor="@id/search_bar"> <!-- Search suggestions/results go here (ScrollView, RecyclerView, etc.). --> </com.google.android.material.search.SearchView>

在源码中这些内容会被放进contentContainer(见 SearchView.java 的addView重写)。仓库 Catalog 的 SearchFragment.java 与 SearchRecyclerDemoActivity.java 是完整的参考实现。

7. 滚动行为三种模式

SearchBar支持三种滚动形态:固定、滚动消失、滚动抬升。

固定模式(Fixed)

SearchBar置于布局内容顶部,不设置任何滚动行为或AppBarLayout,内容在下方滚动而SearchBar保持固定。

滚动消失模式(Scroll-away)

使用顶层CoordinatorLayout,把SearchBar放入AppBarLayout,并将AppBarLayout放在滚动视图(通常是RecyclerViewNestedScrollView之后,同时在滚动视图上设置:

app:layout_behavior="@string/searchbar_scrolling_view_behavior"

该行为(searchbar_scrolling_view_behavior定义于 strings.xml,对应SearchBarBehavior)会使AppBarLayout透明、无阴影,并调整滚动子视图,让SearchBar悬浮覆盖在内容之上。若应用是 edge-to-edge 布局,建议给AppBarLayout添加app:statusBarForeground="?attr/colorSurface",避免滚动时SearchBar与状态栏内容重叠。

滚动抬升模式(Lift on Scroll)

同样使用顶层CoordinatorLayout+AppBarLayout,但在滚动视图上设置:

app:layout_behavior="@string/appbar_scrolling_view_behavior"

并在SearchBar上设置:

app:liftOnScroll="true" app:liftOnScrollColor="?attr/colorSurfaceContainerHighest"

这样当AppBarLayout滚动抬升时,SearchBar会改变颜色以凸显层次。

8. 综合示例:Scroll-away 模式完整布局

<androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- NestedScrollingChild goes here (NestedScrollView, RecyclerView, etc.). --> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/searchbar_scrolling_view_behavior"> <!-- Screen content goes here. --> </androidx.core.widget.NestedScrollView> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <com.google.android.material.search.SearchBar android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/searchbar_hint" /> </com.google.android.material.appbar.AppBarLayout> <com.google.android.material.search.SearchView android:layout_width="match_parent" android:layout_height="match_parent" android:hint="@string/searchbar_hint" app:layout_anchor="@id/search_bar"> <!-- Search suggestions/results go here (ScrollView, RecyclerView, etc.). --> </com.google.android.material.search.SearchView> </androidx.coordinatorlayout.widget.CoordinatorLayout>

SearchBarSearchView放在同一个CoordinatorLayout中并通过app:layout_anchor关联,二者会自动完成接线:点击SearchBar显示SearchView,并具备展开/收起动画(SearchView实现了CoordinatorLayout.AttachedBehavior,见 SearchView.java)。如果无法使用CoordinatorLayout,可调用SearchView#setUpWithSearchBar达到相同效果。

Lift on scroll 模式的完整布局与上面类似,仅需将滚动视图的 behavior 改为@string/appbar_scrolling_view_behavior,并在SearchBar上增加app:liftOnScrollapp:liftOnScrollColor

9. Toolbar 过渡(上下文多选等场景)

SearchBar还支持与Toolbar之间的双向过渡,例如上下文多选流程。过渡以展开/收起动画实现,分别通过SearchBar#expandSearchBar#collapse触发(见 SearchBar.java);若同时使用AppBarLayout,可将AppBarLayout引用传入这两个方法,使动画考虑其可见性与偏移。最后,在返回键处理逻辑中加入以下代码,让用户按系统返回键时把上下文Toolbar收回到SearchBar

if (searchBar.collapse(contextualToolbar, appBarLayout)) { // Clear selection. return; }

八、仓库内的参考实现

  • 组件源码:lib/java/com/google/android/material/search(SearchBar.javaSearchView.java及两个动画 Helper)
  • 资源定义:attrs.xml、styles.xml、dimens.xml
  • 布局模板:mtrl_search_bar.xml、mtrl_search_view.xml
  • Catalog 示例:catalog/java/io/material/catalog/search,包括SearchFragmentSearchRecyclerDemoActivitySearchBarWithAppBarIconsDemoActivity(AppBar with Search 的图标外置示例)以及复用的 SearchDemoUtils.java
  • 主题样式参考:lib/java/com/google/android/material/search/res/values/styles.xml 中的ThemeOverlay.Material3Expressive.AppBarWithSearch相关定义

通过组合上述属性、动画与滚动行为,你可以在应用中快速构建出一套符合 Material 3 规范的完整搜索体验,并获得与系统级搜索一致的交互质感。

  • UI组件
  • 移动开发
  • 设计系统

【免费下载链接】material-components-android

[MAINTENANCE MODE] Modular and customizable Material Design UI components for Android

项目地址:https://gitcode.com/gh_mirrors/ma/material-components-android
点击查看免费下载
上一篇:为什么你的 Fight Club 5e 总缺内容?FightClub5eXML 零基础完整配置指南
下一篇:机器学习过拟合终极指南:7大正则化技术深度解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 16:18:58

Windows 11下MediaPipe C++编译实战指南

1. 为什么在 Windows 11 上用 C 编译 MediaPipe 是件“既必要又痛苦”的事&#xff1f;MediaPipe 不是那种装个 pip 就能跑的 Python 库——它本质是一个高度优化的跨平台多媒体处理框架&#xff0c;底层由 C 实现&#xff0c;Python 接口只是薄薄一层胶水。当你需要做手势识别…

作者头像 李华