شريط البحث

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

يتم عرض شريطَي بحث. يحتوي الحقل على يمين الصفحة على حقل نصي فقط.
  يحتوي شريط البحث على يمين الصفحة على حقل نص واقتراح بحث تحته.
الشكل 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 إدخال النص ويُعدِّل الحالة كلما تغيّر النص في حقل الإدخال.
    • تتحكّم حالة The 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,
    // 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 lambda عندما يكتب المستخدِم نصًا أو يحذفه في شريط البحث.
  • يحتوي الرمز SearchBarDefaults.InputField على رمز leadingIcon يضيف رمز بحث إلى بداية حقل الإدخال، ورمز trailingIcon يضيف رمز "خيارات إضافية" إلى نهاية حقل الإدخال. يمكنك هنا منح المستخدم خيارات sorting وfiltering.
  • تستدعي دالة onSearch = { … } دالة onSearch lambda وتصغّر شريط البحث عند إرسال طلب البحث.
  • يعالج LazyColumn عددًا كبيرًا من نتائج البحث بكفاءة. وتتمّ إعادة المرور في قائمة searchResults وعرض كل نتيجة كListItem.
  • يعرض كل عنصر ListItem قابل للإنشاء نص العنصر، ونصًا يعرض معلومات إضافية، ورمز نجمة كleadingContent للعنصر. في هذا المثال، يتم عرض خيار لتفضيل العنصر.
  • لمعرفة منطق الفلترة، اطّلِع على CustomizableSearchBarExample في رمز المصدر الكامل على GitHub.

النتيجة

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

مصادر إضافية