Android SearchView 搜索框

Tags: android

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

背景: 天气预报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> 
                <action android:name="android.intent.action.SEARCH" /> 
                <!-- No category needed, because the Intent will specify this class component--> 
            </intent-filter> 
            <!-- Points to searchable meta data. --> 
            <meta-data android:name="android.app.searchable" 
                       android:resource="@xml/searchable" /> 
            <!-- /关注1 -->
    
        </activity> 
        <provider android: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-data android:name="android.app.default_searchable" 
                   android:value="com.lichen.weather.WeatherActivity" /> 
        <!-- /关注2 -->
    
    </application>

 2. menu菜单里面加入    

<menu xmlns:android="http://schemas.android.com/apk/res/android" > 
    <item android: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的  protected void onNewIntent(Intent intent) {}  来交互.    

@Override 
protected void onNewIntent(Intent intent) { 
    handleIntent(intent); 
}

private void 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 
public boolean 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); 
    return true; 
}

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

 5. 需要数据库支持    

public class CityDatabaseHelper extends SQLiteOpenHelper { 
    protected static final String DATABASE_NAME = "city.db"; 
    protected static final int 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};  
    
    private static final HashMap<String,String> mColumnMap = buildColumnMap(); 
    
    public CityDatabaseHelper(Context context) { 
        super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 
    
    private static 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 
    public void 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 
    public void 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    

public class CityContentProvider extends ContentProvider { 
    public static final String AUTHORITY = "com.lichen.cityprovider"; 
    private SQLiteDatabase db; 
    private CityDatabaseHelper dbHelper; 
    private static final int QUERY_NORMAL= 1; 
    private static final int QUERY_BY_ID= 2; 
    private  static final  int QUERY_SEARCH_CITY_NAME= 3; 
    public static 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 
    public boolean 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: 
            throw new IllegalArgumentException("Unknown Uri: " + uri); 
        } 
    } 
}

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

本文链接:http://www.4byte.cn/learning/119753/android-searchview-sou-suo-kuang.html



相关文章