詳細解讀Android中的搜索框—— SearchView


本篇講的是如何用searchView實現搜索框,其實原理和之前的沒啥差別,也算是個復習吧。

一、Manifest.xml

這里我用一個activity進行信息的輸入和展示,配置方式還是老樣子,寫一個輸入框的配置文件,然后寫定一個action

復制代碼
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kale.searchview"
    android:versionCode="1"
    android:versionName="1.0" ><uses-permission android:name="android.permission.READ_CONTACTS"/><uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="18" /><application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" ><activity
            android:name=".MainActivity"
            android:label="@string/app_name" 
            android:windowSoftInputMode = "adjustPan"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><action android:name="android.intent.action.SEARCH" /></intent-filter><meta-data  
                android:name="android.app.searchable"  
                android:resource="@xml/searchable" /></activity></application></manifest>
復制代碼

 

二、searchable.xml

復制代碼
<?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"  
    android:icon="@drawable/ic_launcher"
    android:searchMode="queryRewriteFromText" />
復制代碼

 

三、MainActivity

3.1 設置SearchView

貼代碼之前先說下searchview的設置,searchview有很多設置方案,詳細可以參考官方的文檔,下面是我舉得幾個例子:

復制代碼
mSearchView = (SearchView) findViewById(R.id.search);
        /**
         * 默認情況下, search widget是"iconified“的,只是用一個圖標 來表示它(一個放大鏡),
         * 當用戶按下它的時候才顯示search box . 你可以調用setIconifiedByDefault(false)讓search
         * box默認都被顯示。 你也可以調用setIconified()讓它以iconified“的形式顯示。
         */
        mSearchView.setIconifiedByDefault(true);
        /**
         * 默認情況下是沒提交搜索的按鈕,所以用戶必須在鍵盤上按下"enter"鍵來提交搜索.你可以同過setSubmitButtonEnabled(
         * true)來添加一個提交按鈕("submit" button)
         * 設置true后,右邊會出現一個箭頭按鈕。如果用戶沒有輸入,就不會觸發提交(submit)事件
         */
        mSearchView.setSubmitButtonEnabled(true);
        /**
         * 初始是否已經是展開的狀態
         * 寫上此句后searchView初始展開的,也就是是可以點擊輸入的狀態,如果不寫,那么就需要點擊下放大鏡,才能展開出現輸入框
         */
        mSearchView.onActionViewExpanded();
        // 設置search view的背景色
        mSearchView.setBackgroundColor(0x22ff00ff);
        /**
         * 默認情況下, search widget是"iconified“的,只是用一個圖標 來表示它(一個放大鏡),
         * 當用戶按下它的時候才顯示search box . 你可以調用setIconifiedByDefault(false)讓search
         * box默認都被顯示。 你也可以調用setIconified()讓它以iconified“的形式顯示。
         */
        mSearchView.setIconifiedByDefault(true);
復制代碼

 

3.2 配置監聽器

這段代碼之前見過,監聽器中的方法會在用戶輸入和提交搜索結果時觸發

復制代碼
mSearchView.setOnQueryTextListener(new OnQueryTextListener() {

            private String TAG = getClass().getSimpleName();

            /*
             * 在輸入時觸發的方法,當字符真正顯示到searchView中才觸發,像是拼音,在舒服法組詞的時候不會觸發
             * 
             * @param queryText
             * 
             * @return false if the SearchView should perform the default action
             * of showing any suggestions if available, true if the action was
             * handled by the listener.
             */
            @Override
            public boolean onQueryTextChange(String queryText) {
                Log.d(TAG, "onQueryTextChange = " + queryText);

                String selection = RawContacts.DISPLAY_NAME_PRIMARY + " LIKE '%" + queryText + "%' " + " OR "
                        + RawContacts.SORT_KEY_PRIMARY + " LIKE '%" + queryText + "%' ";
                // String[] selectionArg = { queryText };
                mCursor = getContentResolver().query(RawContacts.CONTENT_URI, PROJECTION, selection, null, null);
                mAdapter.swapCursor(mCursor); // 交換指針,展示新的數據return true;
            }

            /*
             * 輸入完成后,提交時觸發的方法,一般情況是點擊輸入法中的搜索按鈕才會觸發。表示現在正式提交了
             * 
             * @param queryText
             * 
             * @return true to indicate that it has handled the submit request.
             * Otherwise return false to let the SearchView handle the
             * submission by launching any associated intent.
             */
            @Override
            public boolean onQueryTextSubmit(String queryText) {
                Log.d(TAG, "onQueryTextSubmit = " + queryText);

                if (mSearchView != null) {
                    // 得到輸入管理對象
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    if (imm != null) {
                        // 這將讓鍵盤在所有的情況下都被隱藏,但是一般我們在點擊搜索按鈕后,輸入法都會乖乖的自動隱藏的。
                        imm.hideSoftInputFromWindow(mSearchView.getWindowToken(), 0); // 輸入法如果是顯示狀態,那么就隱藏輸入法                    }
                    mSearchView.clearFocus(); // 不獲取焦點                }
                return true;
            }
        });
復制代碼

 

3.3 全部代碼

復制代碼
package com.kale.searchview;

import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.SimpleCursorAdapter;

public class MainActivity extends ActionBarActivity {

    private SearchView mSearchView;
    private ListView mListView;
    private SimpleCursorAdapter mAdapter;
    private Cursor mCursor;

    static final String[] PROJECTION = new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 得到聯系人名單的指針
        mCursor = getContentResolver().query(RawContacts.CONTENT_URI, PROJECTION, null, null, null);
        // 通過傳入mCursor,將聯系人名字放入listView中。
        mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mCursor,
                new String[] { RawContacts.DISPLAY_NAME_PRIMARY }, new int[] { android.R.id.text1 }, 0);

        mListView = (ListView) findViewById(android.R.id.list);
        mListView.setAdapter(mAdapter);
        mListView.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) {
                    imm.hideSoftInputFromWindow(mListView.getWindowToken(), 0); // 輸入法如果是顯示狀態,那么就隱藏輸入法                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

        mSearchView = (SearchView) findViewById(R.id.search);
        /**
         * 默認情況下, search widget是"iconified“的,只是用一個圖標 來表示它(一個放大鏡),
         * 當用戶按下它的時候才顯示search box . 你可以調用setIconifiedByDefault(false)讓search
         * box默認都被顯示。 你也可以調用setIconified()讓它以iconified“的形式顯示。
         */
        mSearchView.setIconifiedByDefault(true);
        /**
         * 默認情況下是沒提交搜索的按鈕,所以用戶必須在鍵盤上按下"enter"鍵來提交搜索.你可以同過setSubmitButtonEnabled(
         * true)來添加一個提交按鈕("submit" button)
         * 設置true后,右邊會出現一個箭頭按鈕。如果用戶沒有輸入,就不會觸發提交(submit)事件
         */
        mSearchView.setSubmitButtonEnabled(true);
        /**
         * 初始是否已經是展開的狀態
         * 寫上此句后searchView初始展開的,也就是是可以點擊輸入的狀態,如果不寫,那么就需要點擊下放大鏡,才能展開出現輸入框
         */
        mSearchView.onActionViewExpanded();
        // 設置search view的背景色
        mSearchView.setBackgroundColor(0x22ff00ff);
        /**
         * 默認情況下, search widget是"iconified“的,只是用一個圖標 來表示它(一個放大鏡),
         * 當用戶按下它的時候才顯示search box . 你可以調用setIconifiedByDefault(false)讓search
         * box默認都被顯示。 你也可以調用setIconified()讓它以iconified“的形式顯示。
         */
        mSearchView.setIconifiedByDefault(true);
        mSearchView.setOnQueryTextListener(new OnQueryTextListener() {

            private String TAG = getClass().getSimpleName();

            /*
             * 在輸入時觸發的方法,當字符真正顯示到searchView中才觸發,像是拼音,在舒服法組詞的時候不會觸發
             * 
             * @param queryText
             * 
             * @return false if the SearchView should perform the default action
             * of showing any suggestions if available, true if the action was
             * handled by the listener.
             */
            @Override
            public boolean onQueryTextChange(String queryText) {
                Log.d(TAG, "onQueryTextChange = " + queryText);

                String selection = RawContacts.DISPLAY_NAME_PRIMARY + " LIKE '%" + queryText + "%' " + " OR "
                        + RawContacts.SORT_KEY_PRIMARY + " LIKE '%" + queryText + "%' ";
                // String[] selectionArg = { queryText };
                mCursor = getContentResolver().query(RawContacts.CONTENT_URI, PROJECTION, selection, null, null);
                mAdapter.swapCursor(mCursor); // 交換指針,展示新的數據return true;
            }

            /*
             * 輸入完成后,提交時觸發的方法,一般情況是點擊輸入法中的搜索按鈕才會觸發。表示現在正式提交了
             * 
             * @param queryText
             * 
             * @return true to indicate that it has handled the submit request.
             * Otherwise return false to let the SearchView handle the
             * submission by launching any associated intent.
             */
            @Override
            public boolean onQueryTextSubmit(String queryText) {
                Log.d(TAG, "onQueryTextSubmit = " + queryText);

                if (mSearchView != null) {
                    // 得到輸入管理對象
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    if (imm != null) {
                        // 這將讓鍵盤在所有的情況下都被隱藏,但是一般我們在點擊搜索按鈕后,輸入法都會乖乖的自動隱藏的。
                        imm.hideSoftInputFromWindow(mSearchView.getWindowToken(), 0); // 輸入法如果是顯示狀態,那么就隱藏輸入法                    }
                    mSearchView.clearFocus(); // 不獲取焦點                }
                return true;
            }
        });
    }

}
復制代碼

 

四、ActionBar上的搜索框

如果我們想要實現下面這種效果,將搜索框放在actionbar上,該怎么做呢?

  

實現方式在menu菜單中添加一個searchview,然后在初始化菜單的時候進行配置

4.1 options_menu.xml

復制代碼
<!--
/*
** Copyright 2010, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
--><!-- Options Menu for SearchableActivity and WordActivity.
 --><menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/search"
          android:title="@string/search"
          android:icon="@drawable/ic_menu_search"
          android:showAsAction="collapseActionView|ifRoom"
          android:actionViewClass="android.widget.SearchView" /></menu>
復制代碼

 

Java

這里我沒綁定監聽器,其實完全可以在這里給searchview綁定監聽器的。

復制代碼
/* 
     * search widget現在已經被配置好了,系統也能夠把搜索命令發送到你的Searchable activity. 
     * 你也可以在 search widget中使用search suggestions。
     * 
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.options_menu, menu);
        
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
        SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
        searchView.setSearchableInfo(info);

        searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by defaultreturn true;
    }
復制代碼

 

這樣寫完后,search后的結果就會傳送到你想要處理搜索結果的activity中了(本例是當前的activity)

復制代碼
    @Override
    protected void onNewIntent(Intent intent) {
        setIntent(intent);
        handleIntent(intent);
    }

    private void handleIntent(Intent intent) {
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);
            doMySearch(query);
        }
    }

    private void doMySearch(String query) {
        // TODO 自動生成的方法存根
        Toast.makeText(this, "do search " + query, 0).show();
    }
復制代碼

 

全部代碼:

復制代碼
package com.kale.searchview;


import android.app.Activity;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;
import android.view.Menu;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.SimpleCursorAdapter;

public class MainActivity extends Activity {

    private SearchView mSearchView;
    private ListView mListView;
    private SimpleCursorAdapter mAdapter;
    private Cursor mCursor;

    static final String[] PROJECTION = new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 得到聯系人名單的指針
        mCursor = getContentResolver().query(RawContacts.CONTENT_URI, PROJECTION, null, null, null);
        // 通過傳入mCursor,將聯系人名字放入listView中。
        mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mCursor,
                new String[] { RawContacts.DISPLAY_NAME_PRIMARY }, new int[] { android.R.id.text1 }, 0);

        mListView = (ListView) findViewById(android.R.id.list);
        mListView.setAdapter(mAdapter);
        mListView.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) {
                    imm.hideSoftInputFromWindow(mListView.getWindowToken(), 0); // 輸入法如果是顯示狀態,那么就隱藏輸入法                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

        mSearchView = (SearchView) findViewById(R.id.search);
        /**
         * 默認情況下, search widget是"iconified“的,只是用一個圖標 來表示它(一個放大鏡),
         * 當用戶按下它的時候才顯示search box . 你可以調用setIconifiedByDefault(false)讓search
         * box默認都被顯示。 你也可以調用setIconified()讓它以iconified“的形式顯示。
         */
        mSearchView.setIconifiedByDefault(true);
        /**
         * 默認情況下是沒提交搜索的按鈕,所以用戶必須在鍵盤上按下"enter"鍵來提交搜索.你可以同過setSubmitButtonEnabled(
         * true)來添加一個提交按鈕("submit" button)
         * 設置true后,右邊會出現一個箭頭按鈕。如果用戶沒有輸入,就不會觸發提交(submit)事件
         */
        mSearchView.setSubmitButtonEnabled(true);
        /**
         * 初始是否已經是展開的狀態
         * 寫上此句后searchView初始展開的,也就是是可以點擊輸入的狀態,如果不寫,那么就需要點擊下放大鏡,才能展開出現輸入框
         */
        mSearchView.onActionViewExpanded();
        // 設置search view的背景色
        mSearchView.setBackgroundColor(0xff000000);
        /**
         * 默認情況下, search widget是"iconified“的,只是用一個圖標 來表示它(一個放大鏡),
         * 當用戶按下它的時候才顯示search box . 你可以調用setIconifiedByDefault(false)讓search
         * box默認都被顯示。 你也可以調用setIconified()讓它以iconified“的形式顯示。
         */
        mSearchView.setIconifiedByDefault(true);
        mSearchView.setOnQueryTextListener(new OnQueryTextListener() {

            private String TAG = getClass().getSimpleName();

            /*
             * 在輸入時觸發的方法,當字符真正顯示到searchView中才觸發,像是拼音,在舒服法組詞的時候不會觸發
             * 
             * @param queryText
             * 
             * @return false if the SearchView should perform the default action
             * of showing any suggestions if available, true if the action was
             * handled by the listener.
             */
            @Override
            public boolean onQueryTextChange(String queryText) {
                Log.d(TAG, "onQueryTextChange = " + queryText);

                String selection = RawContacts.DISPLAY_NAME_PRIMARY + " LIKE '%" + queryText + "%' " + " OR "
                        + RawContacts.SORT_KEY_PRIMARY + " LIKE '%" + queryText + "%' ";
                // String[] selectionArg = { queryText };
                mCursor = getContentResolver().query(RawContacts.CONTENT_URI, PROJECTION, selection, null, null);
                mAdapter.swapCursor(mCursor); // 交換指針,展示新的數據return true;
            }

            /*
             * 輸入完成后,提交時觸發的方法,一般情況是點擊輸入法中的搜索按鈕才會觸發。表示現在正式提交了
             * 
             * @param queryText
             * 
             * @return true to indicate that it has handled the submit request.
             * Otherwise return false to let the SearchView handle the
             * submission by launching any associated intent.
             */
            @Override
            public boolean onQueryTextSubmit(String queryText) {
                Log.d(TAG, "onQueryTextSubmit = " + queryText);

                if (mSearchView != null) {
                    // 得到輸入管理對象
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    if (imm != null) {
                        // 這將讓鍵盤在所有的情況下都被隱藏,但是一般我們在點擊搜索按鈕后,輸入法都會乖乖的自動隱藏的。
                        imm.hideSoftInputFromWindow(mSearchView.getWindowToken(), 0); // 輸入法如果是顯示狀態,那么就隱藏輸入法                    }
                    mSearchView.clearFocus(); // 不獲取焦點                }
                return true;
            }
        });
    }
    
    
    @Override
    protected void onNewIntent(Intent intent) {
        setIntent(intent);
        handleIntent(intent);
    }

    private void handleIntent(Intent intent) {
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);
            doMySearch(query);
        }
    }

    private void doMySearch(String query) {
        // TODO 自動生成的方法存根
        Toast.makeText(this, "do search " + query, 0).show();
    }
    
    
    
    /* 
     * search widget現在已經被配置好了,系統也能夠把搜索命令發送到你的Searchable activity. 
     * 你也可以在 search widget中使用search suggestions。
     * 
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.options_menu, menu);
        
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
        SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
        searchView.setSearchableInfo(info);

        searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by defaultreturn true;
    }

}
復制代碼

 

源碼下載:http://download.csdn.net/detail/shark0017/8364947

 

關於全局搜索請參考:http://blog.csdn.net/imdxt1986/article/details/7311958

再貼一個之前收集的demo,感覺是比較完善,但不效果不是很好。需要的話可以參考:http://download.csdn.net/detail/shark0017/8365121

 

參考自:

http://blog.csdn.net/hudashi/article/details/7052846







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM