הגדרת ממשק החיפוש

כדאי לנסות את התכונה 'כתיבה מהירה'
Jetpack Compose היא ערכת הכלים המומלצת לבניית ממשק משתמש ב-Android. איך מוסיפים פונקציית חיפוש בחלונית הכתיבה

מומלץ להשתמש בווידג'ט SearchView כפריט בסרגל האפליקציות כדי לספק פונקציונליות חיפוש באפליקציה. כמו כל הפריטים בסרגל האפליקציות, אפשר להגדיר שהווידג'ט SearchView יוצג תמיד או רק כשיש מקום. אפשר גם להגדיר אותה כפעולה שניתן לכווץ, שבה הסמליל SearchView מוצג בהתחלה כסמל, ולאחר מכן תופס את כל שורת האפליקציות כתחום חיפוש כשהמשתמש מקייש על הסמל.

הוספת SearchView לסרגל האפליקציות

כדי להוסיף ווידג'ט SearchView לסרגל האפליקציות, יוצרים קובץ בפרויקט בשם res/menu/options_menu.xml ומוסיפים לקובץ את הקוד הבא. הקוד הזה מגדיר איך ליצור את פריט החיפוש, למשל, האיקון שישמש והכותרת של הפריט. המאפיין collapseActionView מאפשר ל-SearchView להתרחב ולכסות את כל שורת האפליקציות, ולהתכווץ חזרה לפריט רגיל בשורת האפליקציות כשלא משתמשים בו. מכיוון ששטח הסרגל של האפליקציות במכשירי טלפון נייד מוגבל, מומלץ להשתמש במאפיין collapsibleActionView כדי לספק חוויית משתמש טובה יותר.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/search"
        android:title="@string/search_title"
        android:icon="@drawable/ic_search"
        android:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

אם רוצים להשתמש בסמל חיפוש נגיש יותר, יוצרים קובץ ic_search.xml בתיקייה /res/drawable ומוסיפים לו את הקוד הבא:

<vector
    android:height="24dp"
    android:tint="#000000"
    android:viewportHeight="24"
    android:viewportWidth="24"
    android:width="24dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
        <path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

כדי להציג את SearchView בסרגל האפליקציות, צריך לנפח את משאב התפריט בפורמט XML‏ res/menu/options_menu.xml ב-method‏ onCreateOptionsMenu() של הפעילות:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    return true
}

הרצת האפליקציה תיצור משהו כזה:

תמונה שמוצג בה מסך ריק עם סמל חיפוש בסרגל העליון של האפליקציה
איור 1. סמל חיפוש בסרגל העליון של האפליקציה.

הסמל SearchView מופיע בסרגל האפליקציות של האפליקציה, אבל הוא לא פעיל. אם מקישים על סמל החיפוש, מופיע משהו כזה:

תמונה שמראה את תצוגת החיפוש בפעולה
איור 2. SearchView בפעולה.

כדי שהפונקציה SearchView תפעל, צריך להגדיר את אופן הפעולה שלה.SearchView

יצירת הגדרת חיפוש

הגדרת חיפוש קובעת את אופן הפעולה של SearchView, והיא מוגדרת בקובץ res/xml/searchable.xml. הגדרת חיפוש חייבת לכלול לפחות מאפיין android:label שיש לו את אותו ערך כמו המאפיין android:label של האלמנט <application> או של האלמנט <activity> במניפסט של Android. עם זאת, מומלץ גם להוסיף את המאפיין android:hint כדי לתת למשתמש מושג מה להזין בתיבה לחיפוש.

<?xml version="1.0" encoding="utf-8"?>

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_name"
        android:hint="@string/search_hint" />

בקובץ המניפסט של האפליקציה, מגדירים רכיב <meta-data> שמצביע לקובץ res/xml/searchable.xml. מגדירים את הרכיב ב-<activity> שבו רוצים להציג את ה-SearchView.

<activity
android:name=".SearchResultsActivity"
android:exported="false"
android:label="@string/title_activity_search_results"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat.Light">
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>

בשיטה onCreateOptionsMenu() שיוצרים, משייכים את הגדרות החיפוש ל-SearchView באמצעות קריאה ל-setSearchableInfo(SearchableInfo):

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView = menu.findItem(R.id.search).actionView as SearchView
    val component = ComponentName(this, SearchResultsActivity::class.java)
    val searchableInfo = searchManager.getSearchableInfo(component)
    searchView.setSearchableInfo(searchableInfo)
    return true
}

הקריאה ל-getSearchableInfo() מקבלת אובייקט SearchableInfo שנוצר מקובץ ה-XML של הגדרות החיפוש. כשהגדרת החיפוש משויכת בצורה נכונה ל-SearchView והמשתמש שולח שאילתה, ה-SearchView מתחיל פעילות עם הכוונה ACTION_SEARCH. לאחר מכן, צריך פעילות שיכולה לסנן את הכוונה הזו ולטפל בשאילתת החיפוש.

יצירת פעילות שאפשר לחפש

פעילות שאפשר לחפש מסננת את הכוונה ACTION_SEARCH ומחפשת את השאילתה בקבוצת נתונים. כדי ליצור פעילות שאפשר לחפש, מגדירים פעילות לבחירתכם לסינון לפי הכוונה ACTION_SEARCH:

<activity android:name=".SearchResultsActivity" ... >
    ...
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    ...
</activity>

בפעילות שאפשר לחפש, מטפלים בכוונה ACTION_SEARCH על ידי בדיקה שלה ב-method‏ onCreate().

Kotlin

class SearchResultsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_search_results)
        handleIntent(intent)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        handleIntent(intent)
    }

    private fun handleIntent(intent: Intent) {
        if (Intent.ACTION_SEARCH == intent.action) {
            val query = intent.getStringExtra(SearchManager.QUERY)
            Log.d("SEARCH", "Search query was: $query")
        }
    }
}

עכשיו ה-SearchView יכול לקבל את השאילתה של המשתמש ולהתחיל את הפעילות שאפשר לחפש באמצעות הכוונה ACTION_SEARCH.

אחרי שמקבלים את שאילתת החיפוש, אפשר להעביר אותה ל-ViewModel, שבו אפשר להשתמש בה בשכבות אחרות בארכיטקטורה כדי לאחזר את תוצאות החיפוש להצגה.