Android SearchView 搜索框_第1张图片

如果对这个效果感觉不错, 请往下看.

背景: 天气预报app, 本地数据库存储70个大中城市的基本信息, 根据用户输入的或通过搜索框选取的城市, 点击查询按钮后, 异步请求国家气象局数据, 得到返回的json解析并显示.

 

1. 先说AndroidManifest.xml文件

   
   
   
   
  1. <uses-sdk 
  2.     android:minSdkVersion="11" 
  3.     android:targetSdkVersion="16" /> 
  4.  
  5. <application> 
  6.     <activity 
  7.         android:name="com.lichen.weather.WeatherActivity" 
  8.         android:launchMode="singleTop" 
  9.         android:label="@string/app_name" > 
  10.         <intent-filter> 
  11.              
  12.         intent-filter> 
  13.          
  14.          
  15.         <intent-filter> 
  16.             <action android:name="android.intent.action.SEARCH" /> 
  17.              
  18.         intent-filter> 
  19.  
  20.          
  21.         <meta-data android:name="android.app.searchable" 
  22.                    android:resource="@xml/searchable" /> 
  23.          
  24.     activity> 
  25.     <provider android:name="com.lichen.db.CityContentProvider" 
  26.         android:authorities="com.lichen.cityprovider" 
  27.         android:label="@string/app_name">provider> 
  28.      
  29.      
  30.     <meta-data android:name="android.app.default_searchable" 
  31.                android:value="com.lichen.weather.WeatherActivity" /> 
  32.      
  33. application> 

2. menu菜单里面加入

   
   
   
   
  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" > 
  2.  
  3.     <item android:id="@+id/search" 
  4.           android:title="@string/menu_search" 
  5.           android:showAsAction="collapseActionView|ifRoom" 
  6.           android:actionViewClass="android.widget.SearchView" /> 
  7.  
  8. menu> 

3. 然后在res目录下新建xml/searchable.xml

   
   
   
   
  1. xml version="1.0" encoding="utf-8"?> 
  2. <searchable xmlns:android="http://schemas.android.com/apk/res/android" 
  3.         android:label="@string/search_label" 
  4.         android:hint="@string/search_hint" 
  5.         android:searchSuggestAuthority="com.lichen.cityprovider" 
  6.         android:searchSuggestIntentAction="android.intent.action.VIEW" 
  7.         android:searchSuggestIntentData="content://com.lichen.cityprovider/city" 
  8.         android:searchSuggestSelection=" ?" 
  9.         android:searchSuggestThreshold="1"  
  10.         android:includeInGlobalSearch="true"> 
  11.  searchable> 

字符串尽量使用@string/search_label这种方式.

4. Activity中

因为注册Activity的启动方式为android:launchMode="singleTop",需要Activity的protected void onNewIntent(Intent intent) {}来交互.

   
   
   
   
  1. @Override 
  2. protected void onNewIntent(Intent intent) { 
  3.     handleIntent(intent); 
  4.  
  5. private void handleIntent(Intent intent) { 
  6.        if (Intent.ACTION_VIEW.equals(intent.getAction())) { 
  7.            //查询数据库 
  8.            Cursor searchCursor = getContentResolver().query(intent.getData(), nullnullnullnull); 
  9.            if (searchCursor != null && searchCursor.moveToFirst()) { 
  10.             cityInput.setText(searchCursor.getString(searchCursor.getColumnIndex(City.CITY_DESCRIBE))); 
  11.         } 
  12.    } 
  13.  
  14. @Override 
  15. public boolean onCreateOptionsMenu(Menu menu) { 
  16.     getMenuInflater().inflate(R.menu.activity_weather, menu); 
  17.      
  18.     SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); 
  19.     SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView(); 
  20.     searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); 
  21.     searchView.setIconifiedByDefault(false); 
  22.     return true

以上的在网上可以搜索到,接下来是重点...

5. 需要数据库支持

   
   
   
   
  1. public class CityDatabaseHelper extends SQLiteOpenHelper { 
  2.  
  3.     protected static final String DATABASE_NAME = "city.db"
  4.     protected static final int DATABASE_VERSION = 6
  5.     public  String[] columns = new String[] { 
  6.             SearchManager.SUGGEST_COLUMN_TEXT_1, 
  7.             SearchManager.SUGGEST_COLUMN_TEXT_2, 
  8.             SearchManager.SUGGEST_COLUMN_ICON_1, 
  9.             SearchManager.SUGGEST_COLUMN_ICON_2, 
  10.             BaseColumns._ID, 
  11.             SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};  
  12.      
  13.     private static final HashMap mColumnMap = buildColumnMap(); 
  14.      
  15.     public CityDatabaseHelper(Context context) { 
  16.         super(context, DATABASE_NAME, null, DATABASE_VERSION); 
  17.     } 
  18.  
  19.     private static HashMap buildColumnMap() { 
  20.         HashMap map = new HashMap(); 
  21.         map.put(SearchManager.SUGGEST_COLUMN_TEXT_1, City.CITY_DESCRIBE + " as "+SearchManager.SUGGEST_COLUMN_TEXT_1); 
  22.         map.put(SearchManager.SUGGEST_COLUMN_TEXT_2, City.CITY_NICKNAME + " as "+SearchManager.SUGGEST_COLUMN_TEXT_2); 
  23.         map.put(SearchManager.SUGGEST_COLUMN_ICON_1, City.CITY_IMG + " as "+SearchManager.SUGGEST_COLUMN_ICON_1); 
  24.         map.put(SearchManager.SUGGEST_COLUMN_ICON_2, City.CITY_IMG_2 + " as "+SearchManager.SUGGEST_COLUMN_ICON_2); 
  25.         map.put(BaseColumns._ID, "rowid AS " + BaseColumns._ID); 
  26.         map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); 
  27.         return map; 
  28.     } 
  29.      
  30.     @Override 
  31.     public void onCreate(SQLiteDatabase db) { 
  32.         db.execSQL("create table " 
  33.                 + City.TABLE_NAME 
  34.                 + "(_id integer primary key autoincrement, city_id integer, city_name text, city_nickname text, city_describe text, city_img text, city_img_2 text)"); 
  35.     } 
  36.  
  37.     @Override 
  38.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
  39.         db.execSQL("drop table if exists " + City.TABLE_NAME); 
  40.         onCreate(db); 
  41.     } 
  42.  
  43.     /** 
  44.      * 用于ContentProvider调用,使用like的模糊查询
  45.      */ 
  46.     public Cursor search(String keyWord){ 
  47.         SQLiteQueryBuilder builder=new SQLiteQueryBuilder(); 
  48.         builder.setTables(City.TABLE_NAME); 
  49.         builder.setProjectionMap(mColumnMap);    
  50.         SQLiteDatabase db=getReadableDatabase(); 
  51.          
  52.         return builder.query(db, columns, City.CITY_NAME + " like ? " + " or " + City.CITY_NICKNAME +" like ? "new String[]{"%"+keyWord+"%""%"+keyWord+"%"}, nullnull,null); 
  53.     } 

6. 完成searchable.xml里面注册的ContentProvider

   
   
   
   
  1. public class CityContentProvider extends ContentProvider { 
  2.  
  3.     public static final String AUTHORITY = "com.lichen.cityprovider"
  4.      
  5.     private SQLiteDatabase db; 
  6.     private CityDatabaseHelper dbHelper; 
  7.      
  8.     private static final int QUERY_NORMAL= 1
  9.     private static final int QUERY_BY_ID= 2
  10.     private  static final  int QUERY_SEARCH_CITY_NAME= 3
  11.      
  12.     public static UriMatcher uriMatcher; 
  13.     static
  14.         uriMatcher=new UriMatcher(UriMatcher.NO_MATCH); 
  15.          
  16.         uriMatcher.addURI(AUTHORITY,"city", QUERY_NORMAL); 
  17.         uriMatcher.addURI(AUTHORITY,"city/#", QUERY_BY_ID); 
  18.          
  19.         uriMatcher.addURI(AUTHORITY,SearchManager.SUGGEST_URI_PATH_QUERY, QUERY_SEARCH_CITY_NAME); 
  20.         uriMatcher.addURI(AUTHORITY,SearchManager.SUGGEST_URI_PATH_QUERY + "/*", QUERY_SEARCH_CITY_NAME); 
  21.     } 
  22.      
  23.     @Override 
  24.     public boolean onCreate() { 
  25.         dbHelper = new CityDatabaseHelper(getContext()); 
  26.         return dbHelper != null
  27.     } 
  28.  
  29.     @Override 
  30.     public Cursor query(Uri uri, String[] projection, String selection, 
  31.             String[] selectionArgs, String sortOrder) { 
  32.         db = dbHelper.getReadableDatabase(); 
  33.         switch (uriMatcher.match(uri)) { 
  34.         case QUERY_SEARCH_CITY_NAME: 
  35.             return dbHelper.search(selectionArgs[0]); 
  36.         default
  37.             throw new IllegalArgumentException("Unknown Uri: " + uri); 
  38.         } 
  39.     } 

like模糊查询对于大数据量效果可想而知,FTS3的支持还未尝试,详情参考Android SDK里面的Samples/SearchableDictionary