Search Dialog是提供搜索的控件之一,还有一个是上次小例子给出的searchView,关于SearchView的东西后面会说到。本次先从Search Dialog说起,让大家慢慢理解android中搜索的控件的机制,逐渐引出搜索信息传递和搜索配置的知识,铺垫到最后再给大家说searchview的话,大家就能很容易理解。
一、Search Dialog 和 Search View
这两个其实都是一个搜索控件,区别不大,但多少还是有些小的差异的。
不同点:
该文件一般约定为searchable.xml并位于res/xml/目录下。searchable.xml必须以<searchable> element 作为根节点,且至少定义一个属性。
<?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:hint="@string/search_hint" android:label="@string/app_name" android:icon="@drawable/kale"> </searchable>
<activity android:name=".MainActivity" android:label="@string/app_name" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- enable the search dialog to send searches to SearchableActivity --> <meta-data android:name="android.app.default_searchable" android:value="com.kale.searchdialogtest.SearchActivity" /> </activity> <activity android:name="com.kale.searchdialogtest.SearchActivity" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity>
为了方便解释,我们直接看主要代码:
MainActivity:
<activity android:name=".MainActivity" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- enable the search dialog to send searches to SearchableActivity --> <meta-data android:name="android.app.default_searchable" android:value="com.kale.searchdialogtest.SearchActivity" /> </activity>
<!-- enable the search dialog to send searches to SearchableActivity --> <meta-data android:name="android.app.default_searchable" android:value="com.kale.searchdialogtest.SearchActivity" />
1. 必须包含“
android:value”属性,该属性指明了
searchable activity的类名,android:name",
且其值必须为 "android.app.default_searchable"
.<activity android:name="com.kale.searchdialogtest.SearchActivity" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity>
依据建议,用于展示搜索结果的activity应该用singleTop模式,同时要强制写上如下内容。
<intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
如果对activity的隐式启动有所了解的话,我们一眼就看出为什么要这么定义了。在MainActivity中系统会在用户提交搜索时产生一个intent,并且给intent放入搜索词,而且还定义了一个action。系统这时就开始找哪个activity中定义了 <action android:name="android.intent.action.SEARCH" />,找到这个activity后就会自动启动我们的这个searchActivity。至于meta-data中的东西,其实就是一个search的配置信息。
package com.kale.searchdialogtest;public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.show_dialog_button); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onSearchRequested(); } }); } }
很简单吧,通过onSearchRequested()我们就可以让activity中显示出一个search dialog,所以在某种意义上说,search dialog不用程序员进行过多干预。
package com.kale.searchdialogtest; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.show_dialog_button); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onSearchRequested(); } }); } // 重写onSearchRequested方法 @Override public boolean onSearchRequested() { // 除了输入查询的值,还可额外绑定一些数据 Bundle appSearchData = new Bundle(); appSearchData.putString("KEY", "text"); startSearch(null, false, appSearchData, false); // 必须返回true。否则绑定的数据作废 return true; } }
我们在这里面放入了一个键值对,KEY-text。
package com.kale.searchdialogtest; import android.app.Activity; import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; import android.widget.Toast; /** * @author:Jack Tony * @description :真正执行搜索和结果展示的Activity 一旦用户在search dialog中执行search操作, * 系统将启动SearchableActivity 并向其传送ACTION_SEARCH intent. * @date :2015年1月15日 * * 参考自:http://zhouyunan2010.iteye.com/blog/1134147 */ public class SearchActivity extends Activity { protected void onCreate(android.os.Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.search_activity); // Get the intent, verify the action and get the query Intent intent = getIntent(); if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); doMySearch(query); } // 获得额外递送过来的值 Bundle appData = intent.getBundleExtra(SearchManager.APP_DATA); if (appData != null) { String testValue = appData.getString("KEY"); System.out.println("extra data = " + testValue); } } private void doMySearch(String query) { // TODO 自动生成的方法存根 TextView textView = (TextView) findViewById(R.id.search_result_textView); textView.setText(query); Toast.makeText(this, "do search", 0).show(); } }
主要内容是从intent中获得数据,然后进行处理。这里仅仅获得了数据,没有进行真正的搜索。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.kale.searchdialogtest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" 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" > <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>
<activity android:name=".MainActivity" >
<intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity>
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
<meta-data android:name="android.app.default_searchable" android:value="com.kale.searchdialogtest.MainActivity" />
package com.kale.searchdialogtest; import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handleIntent(getIntent()); Button btn = (Button) findViewById(R.id.show_dialog_button); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onSearchRequested(); } }); } 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(); } }
<activity android:name=".MainActivity" android:label="@string/app_name" android:launchMode="singleTop" > <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>
package com.kale.searchdialogtest; import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /** * @author:Jack Tony * @description : * * 当系统调用onNewIntent(Intent)的时候,表示activity并不是新建的, 所以getIntent()返回的还是 * 在onCreate()中接受到的intent. * 因此你必须在onNewIntent(Intent)调用setIntent(Intent)来 * (这样保存的intent才被更新,之后你可以同过getIntent()来取得它). * * @date :2015年1月15日 */ public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.show_dialog_button); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onSearchRequested(); } }); } @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(); } }
onNewIntent(Intent)的时候,表示
activity并不是新建的, 所以getIntent()返回的还是
在onCreate()中接受到的intent
. 因此你必须在onNewIntent(Intent)调用
setIntent(Intent)来 (这样保存的intent才被更新,之后你可以同过getIntent()来取得它
)