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

אפשר לנסות את הדרך של כתיבת הודעה
‫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>.

<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>

ב-method‏ 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 על ידי בדיקה שלה בשיטה 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, שבו אפשר להשתמש בה בשכבות אחרות של הארכיטקטורה כדי לאחזר את תוצאות החיפוש ולהציג אותן.