使用搜索栏实现搜索功能。搜索栏是一个持久性搜索字段,可让用户输入关键字或短语,以在您的应用中显示相关结果。如果搜索是应用的主要功能,建议使用搜索栏。
API Surface
使用 SearchBar 可组合项实现搜索栏。此可组合项的关键参数包括以下内容:
inputField:定义搜索栏的输入字段。它通常使用SearchBarDefaults.InputField,后者允许自定义以下内容:query:要在输入字段中显示的查询文本。onQueryChange:用于处理查询字符串更改的 lambda。
expanded:一个布尔值,用于指示搜索栏是否展开即可显示建议或过滤后的结果。onExpandedChange:用于处理下拉列表展开状态更改的 lambda。content:此搜索栏的内容,用于在inputField下方显示搜索结果。
带建议的搜索栏
以下代码段展示了带建议的 SearchBar 的基本实现:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun SimpleSearchBar( textFieldState: TextFieldState, onSearch: (String) -> Unit, searchResults: List<String>, modifier: Modifier = Modifier ) { // Controls expansion state of the search bar var expanded by rememberSaveable { mutableStateOf(false) } Box( modifier .fillMaxSize() .semantics { isTraversalGroup = true } ) { SearchBar( modifier = Modifier .align(Alignment.TopCenter) .semantics { traversalIndex = 0f }, inputField = { SearchBarDefaults.InputField( query = textFieldState.text.toString(), onQueryChange = { textFieldState.edit { replace(0, length, it) } }, onSearch = { onSearch(textFieldState.text.toString()) expanded = false }, expanded = expanded, onExpandedChange = { expanded = it }, placeholder = { Text("Search") } ) }, expanded = expanded, onExpandedChange = { expanded = it }, ) { // Display search results in a scrollable column Column(Modifier.verticalScroll(rememberScrollState())) { searchResults.forEach { result -> ListItem( headlineContent = { Text(result) }, modifier = Modifier .clickable { textFieldState.edit { replace(0, length, result) } expanded = false } .fillMaxWidth() ) } } } } }
代码要点
rememberSaveable可确保在配置更改后保留搜索栏是展开还是收起的状态。它会在配置更改期间销毁 activity 之前,将记住的值写入宿主 activity 的savedInstanceState软件包。semantics修饰符用于控制 TalkBack 遍历顺序。- 为
Box设置isTraversalGroup,以将其所有子可组合项分组。 - 设置
traversalIndex以指定 TalkBack 从每个组对等项读取无障碍信息的顺序。TalkBack 会先读取具有负值(例如-1)的对等项的无障碍 信息,然后再读取具有正值(例如1)的对等项的无障碍 信息。由于该值是浮点数,因此您可以通过在每个对等项上设置介于-1.0和1.0之间的值来指定许多对等项的自定义顺序。
- 为
SearchBar包含用于用户输入的inputField和用于Column显示搜索建议的 。SearchBarDefaults.InputField用于创建输入字段并处理用户查询的更改。onQueryChange用于处理文本输入,并在输入字段中的文本发生更改时更新状态。expanded状态用于控制建议列表的可见性。
searchResults.forEach { result -> … }用于遍历searchResults列表,并为每个结果创建一个ListItem。- 点击
ListItem后,它会更新textFieldState,收起 搜索栏,并使用所选搜索结果填充textField。
- 点击
结果
带过滤列表的搜索栏
此示例展示了一个 SearchBar,该搜索栏会根据用户的搜索查询过滤列表:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun CustomizableSearchBar( query: String, onQueryChange: (String) -> Unit, onSearch: (String) -> Unit, searchResults: List<String>, onResultClick: (String) -> Unit, modifier: Modifier = Modifier, // Customization options placeholder: @Composable () -> Unit = { Text("Search") }, leadingIcon: @Composable (() -> Unit)? = { Icon(Icons.Default.Search, contentDescription = "Search") }, trailingIcon: @Composable (() -> Unit)? = null, supportingContent: (@Composable (String) -> Unit)? = null, leadingContent: (@Composable () -> Unit)? = null, ) { // Track expanded state of search bar var expanded by rememberSaveable { mutableStateOf(false) } Box( modifier .fillMaxSize() .semantics { isTraversalGroup = true } ) { SearchBar( modifier = Modifier .align(Alignment.TopCenter) .semantics { traversalIndex = 0f }, inputField = { // Customizable input field implementation SearchBarDefaults.InputField( query = query, onQueryChange = onQueryChange, onSearch = { onSearch(query) expanded = false }, expanded = expanded, onExpandedChange = { expanded = it }, placeholder = placeholder, leadingIcon = leadingIcon, trailingIcon = trailingIcon ) }, expanded = expanded, onExpandedChange = { expanded = it }, ) { // Show search results in a lazy column for better performance LazyColumn { items(count = searchResults.size) { index -> val resultText = searchResults[index] ListItem( headlineContent = { Text(resultText) }, supportingContent = supportingContent?.let { { it(resultText) } }, leadingContent = leadingContent, colors = ListItemDefaults.colors(containerColor = Color.Transparent), modifier = Modifier .clickable { onResultClick(resultText) expanded = false } .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 4.dp) ) } } } } }
代码要点
- 每当用户在搜索栏中输入或删除文本时,系统都会调用
onQueryChangelambda 函数。 SearchBarDefaults.InputField包含一个leadingIcon(用于在输入字段的开头添加搜索图标)和一个trailingIcon(用于在输入字段的末尾添加“更多选项”图标)。您可以在此处向用户提供排序和过滤选项。onSearch = { … }会在提交搜索时调用onSearchlambda 并收起搜索栏 。LazyColumn可高效处理可能数量众多的搜索结果。它会遍历searchResults列表,并将每个结果显示为ListItem。- 每个
ListItem可组合项都会显示项文本、显示其他信息的文本以及星形图标作为项的leadingContent。在此示例中,系统会显示一个用于将项设为收藏的选项。 - 如需了解过滤逻辑,请参阅
CustomizableSearchBarExample在 完整 源代码在 GitHub。
结果
其他资源
- Material Design:搜索栏