• 详细解读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 default
            return 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 default
            return 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

  • 相关阅读:
    [puppet]如何设置全局exec path
    noVNC配置小结
    [CloudOps]解决Windows系列镜像在Openstack上蓝屏
    解决 /usr/bin/env: php: No such file or directory
    构建一个多区域的公有云平台:Stacklab
    ssh自动添加hostkey到know_hosts
    A few thoughts about Open Source Software
    简单翻译:Understanding Linux Network Internals 2.2. net_device Structure
    近期小结
    [Music]《our love will always last》
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4226675.html
Copyright © 2020-2023  润新知