android浮動搜尋方塊的使用

來源:互聯網
上載者:User

標籤:android   懸浮搜尋方塊   searchview   search   

引言

在我們的應用程式中經常需要提供搜尋服務,比如搜尋連絡人, 搜尋商品資訊等等。我們可以自己在布局中自訂我們的搜尋方塊,實現我們的搜尋邏輯。但是還有一種更簡單的方法:使用android系統給我們提供的搜尋功能架構。
在android中,提供兩種實現搜尋功能的方式:search dialog 和 searchView.
search dialog類似於普通的dialog,懸浮於我們的表單之上。樣本圖如下:

searchView通常被嵌套在我們的布局之中,最典型的案例就是在actionBar中使用searchView.是searchView在中的使用。(PS:圖中的放大鏡就是searchView)

不管你使用哪種方式,安卓系統都會發送查詢請求到處理搜尋邏輯的activity中,來實現搜尋功能。
另外,除了普通的文字搜尋外,還提供了一下的搜尋功能:
1.語音搜尋
2.最近搜尋記錄提示
3.自訂搜尋記錄提示
4.google系統搜尋方塊

google系統搜尋方塊

需要注意的是:安卓系統並不會提供搜尋邏輯,也就是說,當系統將搜尋索引鍵傳遞給我們的時候,需要我們自己來處理搜尋邏輯。比如在資料庫中搜尋、在網路中搜尋。
另外,安卓系統也不會顯式地調用我們的搜尋方塊,我們需要自己調用方法來顯示我們的搜尋方塊。
今天我們主要介紹search dialog的使用方式。

基本原理

首先我們來瞭解一下系統搜尋功能的基本原理。
(一)當使用者在搜尋方塊中執行搜尋操作後,系統會自動建立一個Intent,並且將使用者搜尋的關鍵字存放到Intent中。
(二)系統會啟動處理搜尋邏輯的activity(通常可以命名為SearchableActivity)並將intent傳遞給SearchableActivity,然後在SearchableActivity中處理我們的搜尋邏輯。

配置搜尋方塊

第一步,我們需要配置我們搜尋方塊的xml檔案,其中包括一些屬性比如:語音搜尋,搜尋提示和搜尋記錄等等。
設定檔通常命名為searchable.xml 並且必須 存放在我們工程的res/xml目錄中(沒有就建立一個)
(PS:系統使用這個設定檔來執行個體化SearchableInfo對象,這個對象是提供搜尋相關的中繼資料的,比如SearchableActivity的類名,搜尋索引鍵的類型等等。但是我們不能自己執行個體化SearchableInfo 對象,只能通過設定檔的方式來設定)
下面是searchable.xml設定檔的內容

searchable.xml

<?xml version="1.0" encoding="utf-8"?><searchable xmlns:android="http://schemas.android.com/apk/res/android"    android:hint="@string/searchHint"    android:label="@string/searchLabel" ></searchable>

設定檔的根節點必須是searchable ,其中label是必須的,它的值為一個string資源引用,通常是應用程式的名稱(儘管它是一個必須的屬性,但通常情況下是不顯示出來的,除非你開啟了搜尋建議功能)。
android:hint是配置搜尋方塊的輸入提示資訊,雖然不是必須的屬性,但是強烈建議設定這個屬性,以便使用者輸入搜尋資訊的時候,可是知道能輸入那些搜尋資訊。
以配置很多的屬性,但大部分屬性都只是在使用搜尋建議和語音搜尋時進行配置。

SearchableActivity

第二步, 我們建立SearchableActivity來處理搜尋邏輯並且顯示搜尋結果。
我們需要在android-manifest.xml檔案中配置SearchableActivity的一些屬性,來將它指定為處理搜尋邏輯的activity

android-manifest.xml

<application ... >    <activity android:name=".SearchableActivity" >        <intent-filter>            <action android:name="android.intent.action.SEARCH" />        </intent-filter>        <meta-data android:name="android.app.searchable"                   android:resource="@xml/searchable"/>    </activity>    ...</application>

首先在intent-filter節點中添加 ACTION_SEARCH的action。然後再meta-data節點中的name屬性必須為android.app.searchable,resource屬性為我們的設定檔searchable.xml
注意:我們並不需要在intent-filter中配置category,因為SearchManager會根據SearchableActivity的componentName,顯示地傳遞資料給它。
查看下列SearchManager.class的源碼,我們可以知道這是怎麼實現的。

SearchManager.class

 /**     * Starts the global search activity.     */    /* package */ void startGlobalSearch(String initialQuery, boolean selectInitialQuery,            Bundle appSearchData, Rect sourceBounds) {            //這是我們的searchableActivity        ComponentName globalSearchActivity = getGlobalSearchActivity();        if (globalSearchActivity == null) {            Log.w(TAG, "No global search activity found.");            return;        }        Intent intent = new Intent(INTENT_ACTION_GLOBAL_SEARCH);        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        //顯示傳遞        intent.setComponent(globalSearchActivity);        // Make sure that we have a Bundle to put source in        if (appSearchData == null) {            appSearchData = new Bundle();        } else {            appSearchData = new Bundle(appSearchData);        }        // Set source to package name of app that starts global search, if not set already.        if (!appSearchData.containsKey("source")) {            appSearchData.putString("source", mContext.getPackageName());        }        //查詢的資料        intent.putExtra(APP_DATA, appSearchData);        if (!TextUtils.isEmpty(initialQuery)) {            intent.putExtra(QUERY, initialQuery);        }        if (selectInitialQuery) {            intent.putExtra(EXTRA_SELECT_QUERY, selectInitialQuery);        }        intent.setSourceBounds(sourceBounds);        try {            if (DBG) Log.d(TAG, "Starting global search: " + intent.toUri(0));            mContext.startActivity(intent);        } catch (ActivityNotFoundException ex) {            Log.e(TAG, "Global search activity not found: " + globalSearchActivity);        }    }

一般而言,查詢到的資料都是通過一個ListView來展示的,所以,我們可以讓SearchableActivity繼承ListActivity來方便操作。

在SearchableActivity中,我們需要完成三件事:
1.接受查詢參數
當使用者執行搜尋操作的時候,系統通過intent傳遞名為QUERY 的資料,其中包含的就是我們的搜尋索引鍵,我們可以在intent中接受QUERY資料

public class SearchActivity extends ListActivity{            //測試資料     private String[][] datas = { { "activity", "actionbar", "animation", "android" },            { "bundle", "block", "bluetooth", "boolean" } };            //查詢結果    private String[] result;    private Intent intent;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_search);    intent = getIntent();        // 判斷是否是搜尋請求        if (Intent.ACTION_SEARCH.equals(intent.getAction()))        {            // 擷取搜尋的查詢內容(關鍵字)            String query = intent.getStringExtra(SearchManager.QUERY);

2.根據查詢參數查詢資料

擷取到查詢關鍵字query後,我們就可以執行我們的查詢邏輯了。

    // 執行相應的查詢動作            boolean isSuccess =queryContact(query);
private boolean queryContact(String query)    {        for (String[] ss : datas)        {            for (String s : ss)            {                if (s.contains(query)){                    result = ss;                    return true;                }            }        }        return false;    }

queryContact方法是我寫的類比查詢字典的方法。這裡可以換成在資料庫或者網路中查詢資料。

3.顯示查詢到的資料
查詢到資料中,我們需要將資料顯示到ListView中,並且當使用者點擊某一查詢結果時,將查詢結果返回給MainActivity.

intent = new Intent(SearchActivity.this, MainActivity.class);            if(isSuccess){                setListAdapter(new ArrayAdapter<>(this,                        android.R.layout.simple_list_item_1, result));                getListView().setOnItemClickListener( new OnItemClickListener()                {                    @Override                    public void onItemClick(AdapterView<?> parent, View view,                            int position, long id)                    {                        intent.putExtra("name", result[position]);                        startActivity(intent);                    }                });            }else{            Toast.makeText(this, "沒有查詢到資料", Toast.LENGTH_SHORT).show();            startActivity(intent);            }        }    }
使用搜尋方塊

最後,我們就需要在MainActivity中使用我們的搜尋方塊了。由於前面說過,搜尋方塊預設情況下是隱藏的,需要我們自己來調用。在調用之前,我們還需要在manifest檔案中進行配置,指定使用searchableActivity.

  <activity            android:name=".MainActivity"            android:label="@string/app_name" >                <!-- enable the search dialog to send searches to SearchableActivity -->        <meta-data android:name="android.app.default_searchable"                   android:value=".SearchActivity" />            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>

在MianActivity的節點中,我們需要配置meta-data節點,name必須指定為android.app.default_searchable,value表示我們的searchableActivity.
如果想將搜尋方塊指定為全域的,在整個application中都能使用,那就將meta-data節點配置在application節點中。

最後,我們在MainActivity中調用搜尋方塊。
由於不同的裝置的物理按鍵有很大的差異,有些手機有物理的搜尋按鍵,而有些手機是沒有的。所以我們最好自己在activity中通過一個搜尋按鈕來顯式的調用搜尋方塊。另外一種方法是,通過手機軟鍵盤上面的搜尋按鈕來調用搜尋方塊,這需要在OnCreate()中調用 setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL) .
搜尋方塊是一個懸浮於螢幕上的dialog。它不會對activity棧和生命週期引起任何變化。所以當搜尋方塊出現的時候,沒有任何如onPause()的方法被調用。
通過調用onSearchRequested()方法,我們來啟用搜尋方塊。
在MainActivity中,我們點擊button來顯示搜尋方塊,執行搜尋後,將擷取到的搜尋結果顯示在TextView中。

MainActivity.class

public class MainActivity extends ActionBarActivity{    private TextView msg;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        msg=(TextView) findViewById(R.id.msg);    }    @Override    protected void onResume()    {        String name =(String) getIntent().getStringExtra("name");        if(name!=null)        msg.setText(name);        super.onResume();    }    public void search(View view)    {        onSearchRequested();    }}

另外,我們也可以重寫onSearchRequested()方法,在搜尋的同時做一些其他的操作,比如暫停音樂播放等等。

@Overridepublic boolean onSearchRequested() {    pauseMusic();    return super.onSearchRequested();}

另外,如果我們需要對查詢關鍵字加一些限制條件的時候,我們可以調用onSearchRequested()發送一些額外的資料給searchableActivity,searchableActivity中進行處理。

@Overridepublic boolean onSearchRequested() {//查詢參數     Bundle appData = new Bundle();     appData.putBoolean(SearchableActivity.JARGON, true);     startSearch(null, false, appData, false);     return true; }

當searchableActivity接受到傳遞的查詢參數和關鍵字時,就可以進行查詢操作了。

//通過SearchManager.APP_DATA來提取資料Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);if (appData != null) {    boolean jargon = appData.getBoolean(SearchableActivity.JARGON);  //下面這一句表示我們可以進行的操作。。。。  // “select * from ... where word=query and ...=jargon”;}

注意:我們不能再onSearchRequested()方法外調用startSearch方法,任何操作都必須通過onSearchRequested()來調用。

本文參考自android官網:https://developer.android.com/guide/topics/search/search-dialog.html

源碼下載

android浮動搜尋方塊的使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.