نوار جستجو

از نوار جستجو برای پیاده‌سازی عملکرد جستجو استفاده کنید. نوار جستجو فیلد جستجوی ثابتی است که به کاربران امکان می‌دهد کلیدواژه یا عبارتی را برای نمایش نتایج مرتبط در برنامه شما وارد کنند و زمانی توصیه می‌شود که جستجو تمرکز اصلی برنامه شما باشد.

دو نوار جستجو نشان داده شده است. مورد سمت راست فقط فیلد نوشتاری دارد.
  نوار جستجو در سمت راست دارای فیلد نوشتاری و پیشنهاد جستجو در زیر آن است.
شکل ۱. نوار جستجوی پایه (۱) و نوار جستجو با پیشنهاد (۲).

سطح میانای برنامه‌سازی کاربردی

از ترکیب‌پذیر SearchBar برای پیاده‌سازی نوارهای جستجو استفاده کنید. پارامترهای کلیدی برای این composable شامل موارد زیر است:

  • 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 را با نتیجه جستجوی انتخاب‌شده پر می‌کند.

نتیجه

نوار جستجویی نشان داده می‌شود که حرف «a» در آن تایپ شده است. فهرستی حاوی شش پیشنهاد جستجو در زیر نوار جستجو نمایش داده می‌شود.
شکل ۲. نوار جستجویی که پیشنهادها را نشان می‌دهد.

نوار جستجو با فهرست فیلترشده

این نمونه 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 ببینید.

نتیجه

نوار جستجویی نشان داده می‌شود که حاوی عبارت «جستجوی نوشتار اشاره‌شده» است. در زیر نوار جستجو، فهرستی از پیشنهادهای جستجو با نماد ستاره در کنار هر پیشنهاد نمایش داده می‌شود.
شکل ۳.‏ نوار جستجویی با پیشنهادهای مربوط نمایش داده می‌شود.

منابع بیشتر