效果展示。search的suggest展示
点击键盘右下角的搜索 进入搜索结果界面展示:
首先我们定义了BaseActivity用于search 就是图1展示suggestion的
package com.mengqi.base.ui;
import android.app.SearchManager;
import android.content.Context;
import android.os.Bundle;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.widget.SearchView;
import com.actionbarsherlock.widget.SearchView.OnQueryTextListener;
import com.mengqi.base.R;
public class BaseActivity extends SherlockFragmentActivity implements OnQueryTextListener
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.base_frame_left);
}
// 如果要正常搜索必须返回false。如果返回true那么就不执行搜索。
// 看searchView的源码。只有这个监听器为空或者onQueryTextSubmit返回false才执行下面的
// if (mOnQueryChangeListener == null
// || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
// if (mSearchable != null) {
// launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString()); 搜索跳转
// setImeVisibility(false);
// }
// dismissSuggestions();
// }
@Override
public boolean onQueryTextSubmit(String query)
{
return false;
}
// 这个返回什么都没有影响
@Override
public boolean onQueryTextChange(String newText)
{
return false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
menu.add(0, R.id.menu_settings, 12, R.string.settings);
getSupportMenuInflater().inflate(R.menu.search, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
// 这个SearchableInfo 是在AndroidManifest.xml进行初始化的
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setQueryHint(getString(R.string.search_hint));
// searchView.setOnQueryTextListener(this); 这个按照需求要不要处理。如果设置请注意onQueryTextSubmit返回false
return super.onCreateOptionsMenu(menu);
}
}
menu的xml文件 menu_search
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:icon="@drawable/ic_action_search"
android:id="@id/menu_search"
android:orderInCategory="10"
android:title="@string/search"
android:actionViewClass="com.actionbarsherlock.widget.SearchView"
android:showAsAction="ifRoom|collapseActionView" />
</menu>
这个时候界面上ActionBar有了searchView的界面展示但是不能搜索,因为还没有配置SearchableInfo
所以res/xml/searchable.xml 新建
<?xml version="1.0" encoding="utf-8"?>
<searchable android:label="@string/app_name" android:hint="@string/search_hint"
android:searchSuggestAuthority="com.mengqi.base.provider"
android:searchSuggestPath="newsearch" android:searchSuggestSelection="like ?"
android:searchSuggestIntentAction="com.mengqi.base.view"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
android:searchSuggestThreshold="2" android:includeInGlobalSearch="true"
xmlns:android="http://schemas.android.com/apk/res/android" />
这个设置要了解过contentProvider的人才会熟悉。如果不会先去补补吧,,,,,
contentprovider是通过uri进行数据查找的。
uri包含 scheme+authority+path 对应这个里面searchSuggest的相关配置。
如果searchSuggestSelection像上面设置。并且搜索‘187’ ,那么suggest发起的请求uri就是:(可以在自定义的contentProvider的query方法进行打印)
content://com.mengqi.base.provider/newsearch/search_suggest_query?limit=50 并且selectionArgs[0] 的值就是 187
如果没有设置searchSuggestSelection。一样搜索'187',那么suggest发起的uri就是:
content://com.mengqi.base.provider/newsearch/search_suggest_query/187?limit=50并且selectionArgs为null
searchSuggestThreshold表示suggest展示需要最小位数,这我设置的是2.那么我只搜索‘1’那么不会显示。搜索‘18’才开始有显示。(要显示必须是suggest的查询有数据可以返回哈)。
searchSuggestIntentAction 表示展示的suggest的item点击 点击触发一个intent,这个intent的action就是在这设置。
具体这个跳转后面还有详细讲到。
searchableInfo还有配置完成。还要到AndroidManifest.xml继续设置。
<activity android:name="com.mengqi.base.ui.search.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>
<meta-data android:name="android.app.default_searchable"
android:value="com.mengqi.base.ui.search.SearchActivity" />
/**
* CopyRight 2014 ZhuYan
* @author Zhu Yan
*
* All right reserved
*
* Created on 2014-2-20 下午2:59:04
*/
package com.mengqi.base.ui.search;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.widget.SearchView;
import com.mengqi.base.R;
import com.mengqi.base.adapter.SearchAdapter;
/**
* @author Zhu Yan
*
* Created on 2014-2-20 下午2:59:04
*/
public class SearchActivity extends SherlockFragmentActivity implements LoaderCallbacks<Cursor>,OnItemClickListener
{
private final static String TAG = "SearchActivity";
private final static String ACTION_VIEW = "com.mengqi.base.view";
private SearchAdapter adapter;
private ListView listView;
private String query = null;
/**
* @return the query
*/
public String getQuery()
{
return query;
}
@Override
protected void onCreate(Bundle arg0)
{
super.onCreate(arg0);
// get and process search query here
if(!handlerIntent(getIntent())){
finish();
return;
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.fragment_empty_list);
listView = (ListView) findViewById(android.R.id.list);
//虽然我的search结果界面的 跟Suggest的item ui很想但是。这个adpter跟suggest没有关系。我是模仿suggest写的ui
adapter = new SearchAdapter(this);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
/**
*
* @param intent
* @return 如果是suggest的item点击跳转那么返回false,是展示搜索结果 返回true
*/
private boolean handlerIntent(Intent intent)
{
final String queryAction = intent.getAction();
if (Intent.ACTION_SEARCH.equals(queryAction)) {
// doSearchQuery(queryIntent, "onCreate()");
query = intent.getStringExtra(SearchManager.QUERY);
System.out.println( "handlerIntent " +query);
getSupportLoaderManager().restartLoader(0, null, this);
return true;
}else {
System.out.println(queryAction);
System.out.println("data:"+intent.getDataString());
redirectToActivity(intent.getDataString());
return false;
}
}
/**
* @param dataString
*/
private void redirectToActivity(String data)
{
//根据传入的data做出不同的跳转。data来自query查询
}
@Override
protected void onNewIntent(Intent intent)
{
// get and process search query here
handlerIntent(intent);
super.onNewIntent(intent);
}
//我的searchActivity的actionbar一样有searchview控件
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getSupportMenuInflater().inflate(R.menu.search, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setQueryHint(getString(R.string.search_hint));
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId()) {
// case R.id.menu_search:
// System.out.println( "click search");
// onSearchRequested();
// return true;
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1)
{
// System.out.println( "create loader()");
if(id == 0){
return new SearchLoader(SearchActivity.this);
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor)
{
// System.out.println( "no loader finished()");
adapter.changeCursor(cursor);
}
//主要是销毁 activity的时候 关闭cursor
@Override
protected void onDestroy()
{
if(adapter != null){
adapter.changeCursor(null);
}
super.onDestroy();
}
@Override
public void onLoaderReset(Loader<Cursor> loader)
{
loader.reset();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id)
{
Object object = adapter.getItem(position);
if(object != null && object instanceof Cursor){
Cursor cursor = (Cursor) object;
//我的search查询和suggest的返回的数据一样。后面有讲到suggest查询的数据返回
redirectToActivity(cursor.getString(cursor
.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_INTENT_DATA)));
}
}
}
好了现在就是配置suggest的数据模型。suggest因为adapter都是系统提供的。所以我们给suggest查询返回的cursor必须是固定数据格式的。
private final static String[] SearchQuery = new String[]{BaseColumns._ID,
SearchManager.SUGGEST_COLUMN_TEXT_1,SearchManager.SUGGEST_COLUMN_TEXT_2,
SearchManager.SUGGEST_COLUMN_ICON_1,SearchManager.SUGGEST_COLUMN_INTENT_DATA};
这就是我的suggest查询的数据库表项。
_id是必须要的。而且每一项都不一样。
SearchManager.SUGGEST_COLUMN_TEXT_1,是指suggest显示的item的标题。SearchManager.SUGGEST_COLUMN_TEXT_2是副标题。
SearchManager.SUGGEST_COLUMN_ICON_1是指显示的ICON 这个值可以是R.drawable的id值。或者是资源文件的URI。
SearchManager.SUGGEST_COLUMN_INTENT_DATA 是值我们点击suggest的item时候 产生一个intent。intent的action就是在searchable.xml设置的。
intent携带的数据就是这个表象的值。这个值通过intent.getDataString();获取。点击suggest的item产生的item会传递到searchActivity进行处理。
所以在SearchActivity中我有handlerIntent()方法对点击suggest的item或者是点击search进行区分处理。
如果你是要对suggest查询的数据库表没有刚才的 表项可以用别名查询。简单举例:select id as _id,name as suggest_text_1 from .....
如果你是多张表查询让后放到suggest中。我这边想到的是查询表 然后得到cursor 然后读取cursor的数据放到MatrixCursor中。反复操作。最后返回MatrixCursor。
SearchActivity还用到了Loader 看不明白就去查询一下吧。
这个是官网的SearchView讲解,比我说的详细。
http://developer.android.com/guide/topics/search/adding-custom-suggestions.html