شريط البحث

استخدِم شريط البحث لتنفيذ وظيفة البحث. شريط البحث هو حقل بحث دائم يتيح للمستخدمين إدخال كلمة رئيسية أو عبارة لعرض النتائج ذات الصلة داخل تطبيقك، ويُنصح به عندما يكون البحث هو التركيز الأساسي لتطبيقك.

يظهر شريطا بحث. يحتوي النموذج الموجود على اليسار على حقل نصي فقط.
  يحتوي شريط البحث على اليسار على حقل نصي واقتراح بحث تحته.
الشكل 1: شريط بحث أساسي (1) وشريط بحث مع اقتراح (2).

مساحة عرض واجهة برمجة التطبيقات

استخدِم الدالة المركّبة 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 الحفاظ على حالة شريط البحث، سواء كان موسّعًا أو مصغّرًا، عند إجراء تغييرات على الإعدادات. وتكتب القيمة المحفوظة في حزمة 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 بنتيجة البحث المحدّدة.

النتيجة

يظهر شريط بحث مكتوب فيه الحرف &quot;أ&quot;. تظهر قائمة تحتوي على ستة اقتراحات بحث أسفل شريط البحث.
الشكل 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 = { … } دالة lambda onSearch ويصغّر شريط البحث عند إرسال طلب البحث.
  • يتعامل LazyColumn مع عدد كبير من نتائج البحث بكفاءة. تتكرّر هذه الدالة في قائمة searchResults وتعرض كل نتيجة على شكل ListItem.
  • تعرض كل دالة مركّبة ListItem نص العنصر ونصًا يعرض معلومات إضافية ورمز نجمة كـ leadingContent للعنصر. في هذا المثال، يتم تقديم خيار لتفضيل العنصر.
  • للاطّلاع على منطق الفلترة، يمكنك مراجعة CustomizableSearchBarExample في الرمز المصدر الكامل على GitHub.

النتيجة

يظهر شريط بحث يحتوي على الكلمات &quot;البحث النصي&quot; (text search) داخل النص التلميحي. أسفل شريط البحث، تظهر قائمة باقتراحات البحث، وبجانب كل اقتراح رمز نجمة.
الشكل 3. شريط بحث يعرض اقتراحات ذات صلة

مراجع إضافية