แถบค้นหา

ใช้แถบค้นหาเพื่อใช้ฟังก์ชันการค้นหา แถบค้นหาคือช่องค้นหาแบบถาวรที่ให้ผู้ใช้ป้อนคีย์เวิร์ดหรือวลีเพื่อแสดงผลลัพธ์ที่เกี่ยวข้องภายในแอป และขอแนะนำให้ใช้เมื่อการค้นหาเป็นจุดมุ่งหมายหลักของแอป

แถบค้นหา 2 แถบจะปรากฏขึ้น ส่วนทางด้านซ้ายมีเพียงช่องข้อความเท่านั้น
  แถบค้นหาทางด้านขวามีช่องข้อความและการแนะนำการค้นหาอยู่ด้านล่าง
รูปที่ 1 แถบค้นหาพื้นฐาน (1) และแถบค้นหาที่มีคำแนะนำ (2)

แพลตฟอร์ม API

ใช้ Composable SearchBar เพื่อใช้แถบค้นหา พารามิเตอร์หลักสำหรับ Composable นี้มีดังต่อไปนี้

  • 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 ช่วยให้มั่นใจว่าระบบจะคงสถานะการขยายหรือยุบแถบค้นหาไว้แม้จะมีการเปลี่ยนแปลงการกำหนดค่า โดยจะเขียนค่าที่จดจำไว้ลงในแพ็กเกจ savedInstanceState ของกิจกรรมที่โฮสต์ก่อนที่กิจกรรมจะถูกทำลายระหว่างการเปลี่ยนแปลงการกำหนดค่า
  • ตัวแก้ไข semantics จะควบคุมลำดับการส่งผ่านของ TalkBack
    • isTraversalGroup มีการตั้งค่าสำหรับ Box เพื่อจัดกลุ่ม Composable ย่อยทั้งหมด
    • traversalIndex มีไว้เพื่อระบุลำดับที่ TalkBack อ่านข้อมูลการช่วยเหลือพิเศษจากแอปเทียบเท่าแต่ละกลุ่ม TalkBack จะอ่านข้อมูลการช่วยเหลือพิเศษในระดับเดียวกันที่มีค่าเป็นลบ เช่น -1 ก่อนระดับเดียวกันที่มีค่าเป็นบวก เช่น 1 เนื่องจากค่าเป็นแบบลอย คุณจึงระบุลำดับที่กำหนดเองของเพียร์หลายรายการได้โดยตั้งค่าระหว่าง -1.0 ถึง 1.0 ในเพียร์แต่ละรายการ
  • SearchBar มี inputField สำหรับอินพุตของผู้ใช้และ Column เพื่อแสดงการแนะนำการค้นหา
    • SearchBarDefaults.InputField จะสร้างช่องป้อนข้อมูลและจัดการการเปลี่ยนแปลงในคำค้นหาของผู้ใช้
    • onQueryChange จะจัดการการป้อนข้อความและอัปเดตสถานะทุกครั้งที่ข้อความในช่องป้อนข้อมูลมีการเปลี่ยนแปลง
    • สถานะ expanded จะควบคุมระดับการมองเห็นของรายการคำแนะนำ
  • searchResults.forEach { result -> … } จะทำซ้ำผ่านรายการ searchResults และสร้าง ListItem สำหรับผลลัพธ์แต่ละรายการ
    • เมื่อคลิก ListItem ระบบจะอัปเดต textFieldState ยุบแถบค้นหา และเติม textField ด้วยผลการค้นหาที่เลือก

ผลลัพธ์

แถบค้นหาแสดงขึ้นพร้อมตัวอักษร &quot;a&quot; ที่พิมพ์อยู่ภายในแถบ รายการที่มีการแนะนำการค้นหา 6 รายการจะแสดงอยู่ใต้แถบค้นหา
รูปที่ 2 แถบค้นหาพร้อมคำแนะนำที่แสดง

แถบค้นหาพร้อมรายการที่กรองแล้ว

ตัวอย่างนี้แสดง 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)
                    )
                }
            }
        }
    }
}

ประเด็นสำคัญเกี่ยวกับโค้ด

  • ระบบจะเรียกใช้ฟังก์ชัน Lambda onQueryChange ทุกครั้งที่ผู้ใช้พิมพ์หรือลบข้อความในแถบค้นหา
  • SearchBarDefaults.InputField มี leadingIcon ซึ่งจะเพิ่มไอคอนค้นหาที่จุดเริ่มต้นของช่องป้อนข้อมูล และ trailingIcon ซึ่งจะเพิ่มไอคอน "ตัวเลือกเพิ่มเติม" ที่ส่วนท้ายของช่องป้อนข้อมูล ในส่วนนี้ คุณสามารถระบุตัวเลือกการจัดเรียงและการกรองให้แก่ผู้ใช้ได้
  • onSearch = { … } เรียกใช้แลมบ์ดา onSearch และยุบแถบค้นหาเมื่อส่งการค้นหา
  • LazyColumn จัดการผลการค้นหาจำนวนมากได้อย่างมีประสิทธิภาพ โดยจะทำซ้ำผ่านรายการ searchResults และแสดงผลลัพธ์แต่ละรายการเป็น ListItem
  • องค์ประกอบ ListItem แต่ละรายการจะแสดงข้อความของรายการ ข้อความที่แสดงข้อมูลเพิ่มเติม และไอคอนรูปดาวเป็น leadingContent ของรายการ ในตัวอย่างนี้ ระบบจะแสดงตัวเลือกให้เพิ่มรายการเป็นรายการโปรด
  • ดูตรรกะการกรองได้ที่ CustomizableSearchBarExample ในซอร์สโค้ดแบบเต็มใน GitHub

ผลลัพธ์

แถบค้นหาที่มีข้อความแนะนำ &quot;ค้นหาข้อความภายใน&quot; จะปรากฏขึ้น รายการการแนะนำการค้นหาจะปรากฏใต้แถบค้นหา โดยมีไอคอนรูปดาวอยู่ข้างการแนะนำแต่ละรายการ
รูปที่ 3 แถบค้นหาที่มีคำแนะนำที่เกี่ยวข้องแสดงอยู่

แหล่งข้อมูลเพิ่มเติม