如果對這個效果感覺不錯, 請往下看.
背景: 天氣預報app, 本地數據庫存儲70個大中城市的基本信息, 根據用戶輸入的或通過搜索框選取的城市, 點擊查詢按鈕後, 異步請求國家氣象局數據, 得到返回的json解析並顯示.
1. 先說AndroidManifest.xml文件
- <uses-sdk
- android:minSdkVersion="11"
- android:targetSdkVersion="16"/>
- <application>
- <activity
- android:name="com.lichen.weather.WeatherActivity"
- android:launchMode="singleTop"
- android:label="@string/app_name">
- <intent-filter>
- <!-- 省略 -->
- </intent-filter>
- <!-- 關注1 -->
- <!-- Receives the search request. -->
- <intent-filter>
- <actionandroid:name="android.intent.action.SEARCH"/>
- <!-- No category needed, because the Intent will specify this class component-->
- </intent-filter>
- <!-- Points to searchable meta data. -->
- <meta-dataandroid:name="android.app.searchable"
- android:resource="@xml/searchable"/>
- <!-- /關注1 -->
- </activity>
- <providerandroid:name="com.lichen.db.CityContentProvider"
- android:authorities="com.lichen.cityprovider"
- android:label="@string/app_name"></provider>
- <!-- 關注2 -->
- <!-- Points to searchable activity so the whole app can invoke search. -->
- <meta-dataandroid:name="android.app.default_searchable"
- android:value="com.lichen.weather.WeatherActivity"/>
- <!-- /關注2 -->
- </application>
2. menu菜單裡面加入
- <menuxmlns:android="http://schemas.android.com/apk/res/android">
- <itemandroid:id="@+id/search"
- android:title="@string/menu_search"
- android:showAsAction="collapseActionView|ifRoom"
- android:actionViewClass="android.widget.SearchView"/>
- </menu>
3. 然後在res目錄下新建xml/searchable.xml
- <?xml version="1.0" encoding="utf-8"?>
- <searchable xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/search_label"
- android:hint="@string/search_hint"
- android:searchSuggestAuthority="com.lichen.cityprovider"
- android:searchSuggestIntentAction="android.intent.action.VIEW"
- android:searchSuggestIntentData="content://com.lichen.cityprovider/city"
- android:searchSuggestSelection=" ?"
- android:searchSuggestThreshold="1"
- android:includeInGlobalSearch="true">
- </searchable>
字符串盡量使用@string/search_label這種方式.
4. Activity中
因為注冊Activity的啟動方式為android:launchMode="singleTop",需要Activity的protectedvoid onNewIntent(Intent intent) {}來交互.
- @Override
- protectedvoid onNewIntent(Intent intent) {
- handleIntent(intent);
- }
- privatevoid handleIntent(Intent intent) {
- if (Intent.ACTION_VIEW.equals(intent.getAction())) {
- //查詢數據庫
- Cursor searchCursor = getContentResolver().query(intent.getData(), null, null, null, null);
- if (searchCursor != null && searchCursor.moveToFirst()) {
- cityInput.setText(searchCursor.getString(searchCursor.getColumnIndex(City.CITY_DESCRIBE)));
- }
- }
- @Override
- publicboolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.activity_weather, menu);
- SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
- searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
- searchView.setIconifiedByDefault(false);
- returntrue;
- }
以上的在網上可以搜索到,接下來是重點...
5. 需要數據庫支持
- publicclass CityDatabaseHelper extends SQLiteOpenHelper {
- protectedstaticfinal String DATABASE_NAME = "city.db";
- protectedstaticfinalint DATABASE_VERSION = 6;
- public String[] columns = new String[] {
- SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2,
- SearchManager.SUGGEST_COLUMN_ICON_1,
- SearchManager.SUGGEST_COLUMN_ICON_2,
- BaseColumns._ID,
- SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};
- privatestaticfinal HashMap<String,String> mColumnMap = buildColumnMap();
- public CityDatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
- privatestatic HashMap<String,String> buildColumnMap() {
- HashMap<String,String> map = new HashMap<String,String>();
- map.put(SearchManager.SUGGEST_COLUMN_TEXT_1, City.CITY_DESCRIBE + " as "+SearchManager.SUGGEST_COLUMN_TEXT_1);
- map.put(SearchManager.SUGGEST_COLUMN_TEXT_2, City.CITY_NICKNAME + " as "+SearchManager.SUGGEST_COLUMN_TEXT_2);
- map.put(SearchManager.SUGGEST_COLUMN_ICON_1, City.CITY_IMG + " as "+SearchManager.SUGGEST_COLUMN_ICON_1);
- map.put(SearchManager.SUGGEST_COLUMN_ICON_2, City.CITY_IMG_2 + " as "+SearchManager.SUGGEST_COLUMN_ICON_2);
- map.put(BaseColumns._ID, "rowid AS " + BaseColumns._ID);
- map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
- return map;
- }
- @Override
- publicvoid onCreate(SQLiteDatabase db) {
- db.execSQL("create table "
- + City.TABLE_NAME
- + "(_id integer primary key autoincrement, city_id integer, city_name text, city_nickname text, city_describe text, city_img text, city_img_2 text)");
- }
- @Override
- publicvoid onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- db.execSQL("drop table if exists " + City.TABLE_NAME);
- onCreate(db);
- }
- /**
- * 用於ContentProvider調用,使用like的模糊查詢
- */
- public Cursor search(String keyWord){
- SQLiteQueryBuilder builder=new SQLiteQueryBuilder();
- builder.setTables(City.TABLE_NAME);
- builder.setProjectionMap(mColumnMap);
- SQLiteDatabase db=getReadableDatabase();
- return builder.query(db, columns, City.CITY_NAME + " like ? " + " or " + City.CITY_NICKNAME +" like ? ", new String[]{"%"+keyWord+"%", "%"+keyWord+"%"}, null, null,null);
- }
- }
6. 完成searchable.xml裡面注冊的ContentProvider
- publicclass CityContentProvider extends ContentProvider {
- publicstaticfinal String AUTHORITY = "com.lichen.cityprovider";
- private SQLiteDatabase db;
- private CityDatabaseHelper dbHelper;
- privatestaticfinalint QUERY_NORMAL= 1;
- privatestaticfinalint QUERY_BY_ID= 2;
- privatestaticfinalint QUERY_SEARCH_CITY_NAME= 3;
- publicstatic UriMatcher uriMatcher;
- static{
- uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
- uriMatcher.addURI(AUTHORITY,"city", QUERY_NORMAL);
- uriMatcher.addURI(AUTHORITY,"city/#", QUERY_BY_ID);
- uriMatcher.addURI(AUTHORITY,SearchManager.SUGGEST_URI_PATH_QUERY, QUERY_SEARCH_CITY_NAME);
- uriMatcher.addURI(AUTHORITY,SearchManager.SUGGEST_URI_PATH_QUERY + "/*", QUERY_SEARCH_CITY_NAME);
- }
- @Override
- publicboolean onCreate() {
- dbHelper = new CityDatabaseHelper(getContext());
- return dbHelper != null;
- }
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- db = dbHelper.getReadableDatabase();
- switch (uriMatcher.match(uri)) {
- case QUERY_SEARCH_CITY_NAME:
- return dbHelper.search(selectionArgs[0]);
- default:
- thrownew IllegalArgumentException("Unknown Uri: " + uri);
- }
- }
- }
like模糊查詢對於大數據量效果可想而知,FTS3的支持還未嘗試,詳情參考Android SDK裡面的Samples/SearchableDictionary
相關附件下載:
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2013年資料/6月/4日/Android SearchView 搜索框
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11