検索バーを使用して検索機能を実装します。検索バーは永続的な検索フィールドで、ユーザーがキーワードやフレーズを入力してアプリ内の関連する結果を表示できます。検索がアプリの主な機能である場合に推奨されます。
API サーフェス
SearchBar コンポーザブルを使用して検索バーを実装します。このコンポーザブルの主なパラメータは次のとおりです。
inputField: 検索バーの入力フィールドを定義します。通常はSearchBarDefaults.InputFieldを使用します。これにより、次の項目をカスタマイズできます。query: 入力フィールドに表示されるクエリテキスト。onQueryChange: クエリ文字列の変更を処理するラムダ。
expanded: 検索バーが展開されて候補やフィルタされた結果が表示されるかどうかを示すブール値。onExpandedChange: プルダウンの展開状態の変更を処理するラムダ。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を使用すると、検索バーが展開されているか折りたたまれているかが、構成の変更後も保持されます。構成の変更中にアクティビティが破棄される前に、保存された値がホスト アクティビティのsavedInstanceStateバンドルに書き込まれます。semantics修飾子は、TalkBack のトラバーサル順序を制御します。isTraversalGroupはBoxに設定され、すべての子コンポーザブルをグループ化します。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) ) } } } } }
コードに関する主なポイント
- ユーザーが検索バーにテキストを入力または削除するたびに、
onQueryChangeラムダ関数が呼び出されます。 SearchBarDefaults.InputFieldには、入力フィールドの先頭に検索アイコンを追加するleadingIconと、入力フィールドの末尾に [その他のオプション] アイコンを追加するtrailingIconが含まれています。ここで、並べ替えとフィルタのオプションをユーザーに提供できます。onSearch = { … }は、検索が送信されるとonSearchラムダを呼び出し、検索バーを折りたたみます 。LazyColumnは、検索結果が多数になる可能性がある場合に効率的に処理します。searchResultsリストを反復処理し、各結果をListItemとして表示します。- 各
ListItemコンポーザブルには、アイテムのテキスト、追加情報を表示するテキスト、アイテムのleadingContentとして星アイコンが表示されます。この例では、アイテムをお気に入りに追加するオプションが表示されます。 - フィルタリング ロジックについては、
CustomizableSearchBarExampleを GitHub の 完全な ソースコードでご覧ください。
結果
参考情報
- マテリアル デザイン: 検索バー