码迷,mamicode.com
首页 > 移动开发 > 详细

Android Api Demos登顶之路(五十二)Search

时间:2015-08-29 15:32:12      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:apidemo   search   searchdial   menu   查询   

android 为所有需要提供查询功能的activity提供了两种查询方式:search dialog 和searchview
* 这个demo演示了第一种查询方式。
* 基本思路:用户提交查询后,Android系统构造一个Intent并把用户的查询内容放在这个Intent中。然后Android启动你定义的用来处理用户查询的Activity(称为Searchable Activity),并把这个Intent发给该Activity。
* 使用SearchDialog的步骤
* 1.在res/xml目录下创建searchable.xml,用于描述searchdialog的一些属性。
* 2.创建SearchableActivity,这里需要注意的是由于该activity需要验证是否是由查询意图启动的所以在对该activity进行配置时必须在过滤器中指明android.intent.action.SEARCH, 并在meta-data部分指定searchable configuration (指向res/xml/searchable.xml)
* 3.调用:Search Dialog 为屏幕上方的浮动窗口,缺省为不可见的。只有当调用onSearchRequested()或是用户按“Search”键时(不是所有设备都有Search钮,在模拟器上可以用F5)Search Dialog才会显示。
* Searchable.xml,这里需要注意的是在定义label、hint等属性时必须通过String进行引用,否则设置的内容将不起作用,可能会造成searchdialog无法启动,或者某些功能无法实现。

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/search_lable" 
    android:hint="@string/search_hint"
    android:icon="@drawable/star_big_on"
    android:searchMode="showSearchIconAsBadge"
    android:searchSuggestAuthority="com.fishtosky.invokesearch.SearchSuggestionSampleProvider"
    android:searchSuggestSelection=" ? ">
</searchable>

定义SearchableActivity的布局文件:search_result.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这个Activity用来处理用户查询请求,本例只是简单地显示了一下查询内容"/>
    <LinearLayout 
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Query String:"
            />
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/query_string"/>
    </LinearLayout>
    <LinearLayout 
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Query App Data:"
            />
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/query_data"/>

    </LinearLayout>
    <LinearLayout 
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Activity Method:"
            />
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/activity_method"/>
    </LinearLayout>

</LinearLayout>

主布局文件:activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/info" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="ways to invoke search" />

    <Button
        android:id="@+id/search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Search" />

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Opertional search parameters" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Prefill Query:" />

        <EditText
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:id="@+id/et_query"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="App Data:" />

        <EditText
            android:id="@+id/et_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

SearchSuggestionSampleProvider

public class SearchSuggestionSampleProvider extends
        SearchRecentSuggestionsProvider {

    static final String AUTHORITY="com.fishtosky.invokesearch.SearchSuggestionSampleProvider";
    //在此种模式下数据库会记录当前的请求
    static final int MODE=DATABASE_MODE_QUERIES;
    public SearchSuggestionSampleProvider() {
        super();
        setupSuggestions(AUTHORITY, MODE);
    }
}

SearchableActivity:SearchQueryResult

public class SearchQueryResult extends Activity {
    private TextView mQueryString, mQueryData, mActivityMehtod;

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

        mQueryString = (TextView) findViewById(R.id.query_string);
        mQueryData = (TextView) findViewById(R.id.query_data);
        mActivityMehtod = (TextView) findViewById(R.id.activity_method);

        // 获取意图
        Intent queryIntent = getIntent();
        // 判断一下这个意图是否是由用户提交查询时所发出的
        if (Intent.ACTION_SEARCH.equals(queryIntent.getAction())) {
            // 处理查询请求
            doSearchQuery(queryIntent, "onCreate()");
        } else {
            // 如果获取到其它的意图
            mActivityMehtod.setText("onCreate(), but no ACTION_SEARCH intent");
        }
    }

/*
     * ActivityA已经启动过,处于当前应用的Activity堆栈中;
     * 当ActivityA的LaunchMode为SingleTop时,如果ActivityA在栈顶,
     * 且现在要再启动ActivityA,这时会调用onNewIntent()方法
     * 当ActivityA的LaunchMode为SingleInstance,SingleTask时,
     * 如果已经ActivityA已经在堆栈中,那么此时会调用onNewIntent()方法
     * 当ActivityA的LaunchMode为Standard时,由于每次启动ActivityA都是启动新的实例,
     * 和原来启动的没关系,所以不会调用原来ActivityA的onNewIntent方法
     */
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            // 处理查询请求
            doSearchQuery(intent, "onNewIntent()");
        } else {
            // 如果获取到其它的意图
            mActivityMehtod
                    .setText("onNewIntent(), but no ACTION_SEARCH intent");
        }
    }

    private void doSearchQuery(Intent queryIntent, String entrypoint) {
        String queryString = queryIntent.getStringExtra(SearchManager.QUERY);
        mQueryString.setText(queryString);

        // 在最近查询列表中记录查询操作
        SearchRecentSuggestions suggestion = new SearchRecentSuggestions(this,
                SearchSuggestionSampleProvider.AUTHORITY, 
                SearchSuggestionSampleProvider.MODE);
        suggestion.saveRecentQuery(queryString, null);

        Bundle appData=queryIntent.getBundleExtra(SearchManager.APP_DATA);
        if(appData==null){
            mQueryData.setText("<no app data bundle>");
        }else{
            String data=appData.getString("demo_key");
            mQueryData.setText((data==null) ? "<no app data bundle>":data);
        }
        mActivityMehtod.setText(entrypoint);
    }
}

MainActivity

public class MainActivity extends Activity {
    private Button mSearch;
    private Spinner mSpinner;
    private EditText et_query;
    private EditText et_data;

    /*
     * 定义资源数组R.array.search_menumodes中每个条目序号的常量值,所以这里为赋值为0
     * 的必须与资源数组中的第一项对应,赋值为1的必须与第二项对应...
     */
    private static final int MENUMODE_SEARCH_KEY = 0;
    private static final int MENUMODE_MENUITEM = 1;
    private static final int MENUMODE_TYPE_TO_SEARCH = 2;
    private static final int MENUMODE_DISABLED = 3;

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

        mSearch = (Button) findViewById(R.id.search);
        mSpinner = (Spinner) findViewById(R.id.spinner);
        et_query = (EditText) findViewById(R.id.et_query);
        et_data = (EditText) findViewById(R.id.et_data);

        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this, R.array.search_menumodes,
                android.R.layout.simple_spinner_item);
        mSpinner.setAdapter(adapter);

        mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                    int position, long id) {
                if (position == MENUMODE_TYPE_TO_SEARCH) {
                    /*
                     * 设置键盘的输入模式,在该应用的界面下铵任意键将调用应用本身定义的搜索功能
                     * 如果应用本身未定义搜索功能,则此按键模式不起作用,在本例中由于edittext会
                     * 抢占焦点,所以这项设置的作用也不大
                     */
                    setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
                } else {
                    // 设置键盘输入模式为禁用,即在activity下按键将没有任何作用(即启动某项功能的
                    // 快捷键或者按任意键启动搜索功能都将不可用)
                    setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
            }
        });

        mSearch.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                onSearchRequested();
            }
        });
    }

    /*
     * 重写onSearchRequested()方法,当客户端发送启动搜索功能的信号后会将调用此方法
     * 重写该方法我们可以插入本应用中的数据或是上下文中定义的数据搜索功能被启动返回true否则返回false
     */
    @Override
    public boolean onSearchRequested() {
        if (mSpinner.getSelectedItemPosition() == MENUMODE_DISABLED) {
            return false;
        }
        // 预先输入要查询的内容
        String queryPrefill = et_query.getText().toString();
        String queryData = et_data.getText().toString();
        // 利用bundle传递一个上下文中声明的数据,bundle可以传递任意类型的数据
        Bundle bundle = null;
        if (queryData != null) {
            bundle = new Bundle();
            bundle.putString("demo_key", queryData);
        }
        // 启动搜索功能
        startSearch(queryPrefill, false, bundle, false);
        return true;
    }

    // 点击menu键时调用此方法
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // 先将菜单置空
        if (menu.hasVisibleItems()) {
            menu.removeItem(0);
            menu.removeItem(1);
        }
        // 根据下拉列表的选择条目添加菜单
        switch (mSpinner.getSelectedItemPosition()) {
        case MENUMODE_SEARCH_KEY:
            menu.add(0, 0, 0, "(search key)");
            break;
        case MENUMODE_MENUITEM:
            // 添加并设置菜单的快捷键
            menu.add(0, 0, 0, "search").setAlphabeticShortcut(
                    SearchManager.MENU_KEY);
            break;
        case MENUMODE_TYPE_TO_SEARCH:
            menu.add(0, 0, 0, "(type-to-search)");
            break;
        case MENUMODE_DISABLED:
            menu.add(0, 0, 0, "(disabled)");
            break;
        }
        menu.add(0, 1, 0, "Clear History");
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case 0:
            switch (mSpinner.getSelectedItemPosition()) {
            case MENUMODE_SEARCH_KEY:
                new AlertDialog.Builder(this)
                        .setMessage(
                                "To invoke search, dismiss this dialog and press the search key"
                                        + " (F5 on the simulator).")
                        .setPositiveButton("OK", null).show();
                break;
            case MENUMODE_MENUITEM:
                onSearchRequested();
                break;
            case MENUMODE_TYPE_TO_SEARCH:
                new AlertDialog.Builder(this)
                        .setMessage(
                                "To invoke search, dismiss this dialog and srart typing.")
                        .setPositiveButton("OK", null).show();
                break;
            case MENUMODE_DISABLED:
                new AlertDialog.Builder(this)
                        .setMessage("You have disabled search.")
                        .setPositiveButton("OK", null).show();
                break;
            }
            break;
        case 1:
            clearSearchHistory();
        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    // 清空搜索记录
    private void clearSearchHistory() {
        SearchRecentSuggestions suggestion = new SearchRecentSuggestions(this,
                SearchSuggestionSampleProvider.AUTHORITY,
                SearchSuggestionSampleProvider.MODE);
        suggestion.clearHistory();
    }

}

在配置文件中进行配置

<activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data 
                android:name="android.app.default_searchable"
                android:value="com.fishtosky.invokesearch.SearchQueryResult"/>
        </activity>
        <activity 
            android:name="com.fishtosky.invokesearch.SearchQueryResult"
            android:label="@string/result_label"
            android:launchMode="singleTop">
            <intent-filter >
                <action android:name="android.intent.action.SEARCH"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                android:resource="@xml/searchable"/>
        </activity>
        <provider android:name="com.fishtosky.invokesearch.SearchSuggestionSampleProvider"
            android:authorities="com.fishtosky.invokesearch.SearchSuggestionSampleProvider"></provider>

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android Api Demos登顶之路(五十二)Search

标签:apidemo   search   searchdial   menu   查询   

原文地址:http://blog.csdn.net/fishtosky/article/details/48086743

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!