검색창을 사용하여 검색 기능을 구현합니다. 검색창은 사용자가 키워드나 구문을 입력하여 앱 내에서 관련성 높은 결과를 표시할 수 있는 영구 검색창으로, 검색이 앱의 주요 기능인 경우에 권장됩니다.

API 노출 영역
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 탐색 순서를 제어합니다.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, // 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, modifier: Modifier = Modifier ) { // 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
를 참고하세요.
결과

추가 리소스
- Material Design: 검색창