מדריך לדוגמה של SearchView של Android בשימוש בDataBinding

היום נסתכל על ווידג'ט SearchView של Android ונפתח אפליקציה שמסננת ListView לפי הטקסט ששואל. נשתמש ב- DataBinding כדי לחבר את הפריסות בפעילויות ובמתאמים. אם עדיין לא קראת על DataBinding, התייחסי למדריך הזה תחילה להבנה טובה יותר.

SearchView של Android

Android מאפשרת לנו להשתמש בפונקציונליות החיפוש באפליקציה שלנו על ידי הצגת ווידג'ט SearchView בתוך סרגל הכלים/ActionBar או בהכנסתו לתוך פריסה. ווידג'ט SearchView של Android זמין מ- Android 3.0 והלאה. ה- SearchView מוגדר בפריסת ה- XML כפי שמוצג למטה.

<android.support.v7.widget.SearchView
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

קיימים כמה דרכים לחיפוש ב- Android כמו חיפוש קולי, הצעות וכו'. במדריך הזה נשתמש ב-interfaces SearchView.OnQueryTextListener ו-Filterable. ה- interface Filterable מסנן את הטקסט שנשאל על ידי ListView ומציג את שורות ה- ListView התוצאה. ה- interface OnQueryTextListener יכול לזהות שני אירועים.

  1. onQueryTextChange נקרא כאשר המשתמש מקליד תו כל פעם בשדה הטקסט
  2. onQueryTextSubmit מופעל כאשר לוחצים על החיפוש

דוגמת חיפוש ב-Android SearchView

התמונה למטה מציגה את פרויקט דוגמת ה-Android SearchView הסופי. הפרויקט כולל פעילות ומתאם עבור רשימת ה-ListView.

קוד דוגמת Android SearchView

הקובץ activity_main.xml מוצג למטה. הוא כולל ListView עם SearchView בראש. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <android.support.v7.widget.SearchView
            android:id="@+id/search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clickable="true" />

        <ListView
            android:id="@+id/list_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_below="@+id/search" />

    </RelativeLayout>

</layout>

קובץ MainActivity.java מוצג למטה.

package com.journaldev.searchview;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;

import com.journaldev.searchview.databinding.ActivityMainBinding;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding activityMainBinding;
    ListAdapter adapter;

    List<String> arrayList= new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        arrayList.add("January");
        arrayList.add("February");
        arrayList.add("March");
        arrayList.add("April");
        arrayList.add("May");
        arrayList.add("June");
        arrayList.add("July");
        arrayList.add("August");
        arrayList.add("September");
        arrayList.add("October");
        arrayList.add("November");
        arrayList.add("December");

        adapter= new ListAdapter(arrayList);
        activityMainBinding.listView.setAdapter(adapter);

        activityMainBinding.search.setActivated(true);
        activityMainBinding.search.setQueryHint("Type your keyword here");
        activityMainBinding.search.onActionViewExpanded();
        activityMainBinding.search.setIconified(false);
        activityMainBinding.search.clearFocus();

        activityMainBinding.search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {

                adapter.getFilter().filter(newText);

                return false;
            }
        });
    }
}

בקוד לעיל, אנו מעבירים ArrayList של חודשים לאדפטר הרשימה. אנו קוראים לשיטת הפילטר שמוגדרת במחלקת האדפטר בכל פעם שמשתנה הטקסט של שאילתת החיפוש. מחלקת ListAdapter.java נראית כך.

package com.journaldev.searchview;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import com.journaldev.searchview.databinding.RowItemBinding;
import java.util.ArrayList;
import java.util.List;

public class ListAdapter extends BaseAdapter implements Filterable {

    List<String> mData;
    List<String> mStringFilterList;
    ValueFilter valueFilter;
    private LayoutInflater inflater;

    public ListAdapter(List<String> cancel_type) {
        mData=cancel_type;
        mStringFilterList = cancel_type;
    }


    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public String getItem(int position) {
        return mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, final ViewGroup parent) {

        if (inflater == null) {
            inflater = (LayoutInflater) parent.getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
        RowItemBinding rowItemBinding = DataBindingUtil.inflate(inflater, R.layout.row_item, parent, false);
        rowItemBinding.stringName.setText(mData.get(position));


        return rowItemBinding.getRoot();
    }

    @Override
    public Filter getFilter() {
        if (valueFilter == null) {
            valueFilter = new ValueFilter();
        }
        return valueFilter;
    }

    private class ValueFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) {
                List<String> filterList = new ArrayList<>();
                for (int i = 0; i < mStringFilterList.size(); i++) {
                    if ((mStringFilterList.get(i).toUpperCase()).contains(constraint.toString().toUpperCase())) {
                        filterList.add(mStringFilterList.get(i));
                    }
                }
                results.count = filterList.size();
                results.values = filterList;
            } else {
                results.count = mStringFilterList.size();
                results.values = mStringFilterList;
            }
            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) {
            mData = (List<String>) results.values;
            notifyDataSetChanged();
        }

    }

}

כפי שניתן לראות בקוד לעיל, אנו מבצעים סינון באמצעות מחלקה פנימית ValueFilter המרחיבה את מחלקת הפילטר. היא מסננת את הרשימה על ידי בדיקה האם הטקסט של שאילתת החיפוש מתאים למחרוזות הנתונות ב-ArrayList. הפריסה ה-XML עבור שורת ה-ListView נמצאת למטה. row_item.xml

<layout xmlns:android="https://schemas.android.com/apk/res/android">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/stringName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:padding="@dimen/activity_horizontal_margin"
            android:textAllCaps="false"
            android:textAppearance="?android:attr/textAppearanceMedium" />

    </RelativeLayout>

</layout>

הפלט של יישום חיפוש Android SearchView בפעולה מוצג למטה. ה-SearchView המוצג מעלה מחייב אותנו ללחוץ על סמל החיפוש כדי להפעיל את שדה הטקסט. כמו כן, הוא אינו מכיל טקסט רמז/מציין מקום. הוסף את הקוד הבא במחלקת MainActivity כדי לאפשר את ה-SearchView כברירת מחדל ולהציג רמז.

activityMainBinding.search.setActivated(true);
        activityMainBinding.search.setQueryHint("Type your keyword here");
        activityMainBinding.search.onActionViewExpanded();
        activityMainBinding.search.setIconified(false);
        activityMainBinding.search.clearFocus();

ה-SearchView לאחר ההתאמה באופן מותאם אישית נראה כך. זה מסיים את המדריך שלנו ל-Android SearchView. נעמוד על התכונות המתקדמות של SearchView במדריך מאוחר יותר. ניתן להוריד את הפרויקט Android SearchView מהקישור שניתן למטה.

הורד דוגמא לפרויקט Android SearchView

Source:
https://www.digitalocean.com/community/tutorials/android-searchview-example-tutorial