您的位置:首页 > 其它

ShelockActionBar的SearchView的学习

2014-02-26 09:05 453 查看
效果展示。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" />


其中searchActivity就是search的结果展示界面。就是点击键盘右下角的搜索键跳转的界面。

/**
* 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: