検索バーを使用して検索機能を実装します。検索バーは、ユーザーがキーワードやフレーズを入力してアプリ内の関連する結果を表示できるようにする、永続的な検索フィールドです。検索がアプリの主な機能である場合に推奨されます。
API サーフェス
検索バーを実装するには、SearchBar コンポーザブルを使用します。このコンポーザブルの主なパラメータは次のとおりです。
inputField: 検索バーの入力フィールドを定義します。通常はSearchBarDefaults.InputFieldを使用し、次のカスタマイズが可能です。query: 入力フィールドに表示されるクエリテキスト。onQueryChange: クエリ文字列の変更を処理する Lambda。
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は、テキスト入力を処理し、入力フィールドのテキストが変更されるたびに状態を更新します。The 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としての星アイコンを表示します。この例では、アイテムをお気に入りに追加するオプションが表示されています。 - フィルタリング ロジックについては、GitHub の完全なソースコードにある
CustomizableSearchBarExampleをご覧ください。
結果
参考情報
- マテリアル デザイン: 検索バー