この記事で学べること
SearchBar(SearchBar、DockedSearchBar、検索履歴、サジェスト表示)を解説します。
基本SearchBar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchBarExample() {
var query by rememberSaveable { mutableStateOf("") }
var active by rememberSaveable { mutableStateOf(false) }
val history = remember { mutableStateListOf("Kotlin", "Compose", "Room") }
SearchBar(
query = query,
onQueryChange = { query = it },
onSearch = {
if (query.isNotBlank() && query !in history) history.add(0, query)
active = false
},
active = active,
onActiveChange = { active = it },
placeholder = { Text("検索...") },
leadingIcon = { Icon(Icons.Default.Search, null) },
trailingIcon = {
if (query.isNotEmpty()) {
IconButton(onClick = { query = "" }) {
Icon(Icons.Default.Clear, "クリア")
}
}
},
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
) {
history.filter { it.contains(query, ignoreCase = true) }.forEach { item ->
ListItem(
headlineContent = { Text(item) },
leadingContent = { Icon(Icons.Default.History, null) },
modifier = Modifier.clickable { query = item; active = false }
)
}
}
}
DockedSearchBar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DockedSearchExample(items: List<String>) {
var query by remember { mutableStateOf("") }
var active by remember { mutableStateOf(false) }
val filtered = items.filter { it.contains(query, ignoreCase = true) }
Column(Modifier.padding(16.dp)) {
DockedSearchBar(
query = query,
onQueryChange = { query = it },
onSearch = { active = false },
active = active,
onActiveChange = { active = it },
placeholder = { Text("アイテムを検索") },
leadingIcon = { Icon(Icons.Default.Search, null) },
modifier = Modifier.fillMaxWidth()
) {
filtered.take(5).forEach { item ->
ListItem(
headlineContent = { Text(item) },
modifier = Modifier.clickable { query = item; active = false }
)
}
}
Spacer(Modifier.height(16.dp))
LazyColumn {
items(filtered) { item ->
ListItem(headlineContent = { Text(item) })
}
}
}
}
ViewModel連携
@HiltViewModel
class SearchViewModel @Inject constructor(
private val repository: SearchRepository
) : ViewModel() {
private val _query = MutableStateFlow("")
val query = _query.asStateFlow()
val suggestions = _query
.debounce(300)
.filter { it.length >= 2 }
.flatMapLatest { repository.getSuggestions(it) }
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
val results = _query
.debounce(500)
.filter { it.length >= 2 }
.flatMapLatest { repository.search(it) }
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun updateQuery(q: String) { _query.value = q }
}
まとめ
| API | 用途 |
|---|---|
SearchBar |
フルスクリーン検索 |
DockedSearchBar |
インライン検索 |
active |
展開状態制御 |
onSearch |
検索実行 |
-
SearchBarでMaterial3の検索UI -
DockedSearchBarで画面内配置の検索 -
debounceでリアルタイムサジェスト - 検索履歴をリスト表示
8種類のAndroidアプリテンプレート(検索機能対応)を公開しています。
テンプレート一覧 → Gumroad
関連記事:
I publish 8 Android app templates on Gumroad.
Browse templates → Gumroad
Top comments (0)