您的位置:首页 > 移动开发 > Android开发

Android SearchView 搜索框

2013-05-04 00:30 423 查看




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

背景: 天气预报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

本文出自 “wIsper 把技术做成艺术” 博客,请务必保留此出处http://lichen.blog.51cto.com/697816/1192652
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: