Android 4 学习(18):搜索
参考《Professional Android 4 Development》
搜索
通过下面这几种方式可以给应用程序添加搜索功能:
- Search Bar
- Search View
- Quick Search Box
可搜索的Content Provider
首先,要在res./xml目录下创建一个xml文件,例如:
<?xml version=”1.0” encoding=”utf-8”?>
<searchable xmlns:android=”http://schemas.android.com/apk/res/android” android:label=”@string/app_name” android:hint=”@string/search_hint”>
</searchable>
其中,Label一般是应用程序的名称。
为应用程序创建Search Activity
Search Activity和普通的Activity不同,它是一直在back stack的栈顶,每次有新的search activity创建时,不会有将其简单的入栈,因为用户是不会希望按返回键时返回自己前面的查询结果。为了表明该Activity可以被搜索,需要将android.intent.action.SEARCH加入到自己的Intent Filter中,同时需要将前面创建的searchable的xml文件加到meta-data标签中:
<activity android:name=”.DatabaseSkeletonSearchActivity” android:label=”Element Search” android:launchMode=”singleTop”>
<intent-filter>
<action android:name=”android.intent.action.SEARCH” />
<category android:name=”android.intent.category.DEFAULT” />
</intent-filter>
<meta-data android:name=”android.app.searchable” android:resource=”@xml/searchable” />
</activity>
用户进行搜索后,可以在搜索结果中继续搜索,而这种操作会生成新的Intent,而这些Intent可以通过onNewIntent handler来处理:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the launch Intent
parseIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
parseIntent(getIntent());
}
private void parseIntent(Intent intent) {
// If the Activity was started to service a Search request, extract the search query.
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String searchQuery = intent.getStringExtra(SearchManager.QUERY);
// Perform the search
performSearch(searchQuery);
}
}
设置默认的Serach Provider
在应用程序中,最好设置一个Activity,让所有的搜索结果都从这个Activity中出来,设置方法也简单,将下面的配置加到程序配置中就可以了:
<meta-data android:name=”android.app.default_searchable” android:value=”.DatabaseSkeletonSearchActivity” />
使用Cursor Loader的Search Activity示例
import android.app.ListActivity;
import android.app.LoaderManager;
import android.app.SearchManager;
import android.content.ContentUris;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class DatabaseSkeletonSearchActivity extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private static String QUERY_EXTRA_KEY = “QUERY_EXTRA_KEY”;
private SimpleCursorAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a new adapter and bind it to the List View
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, new String[] { MyContentProvider.KEY_COLUMN_1_NAME }, new int[] { android.R.id.text1 }, 0);
setListAdapter(adapter);
// Initiate the Cursor Loader
getLoaderManager().initLoader(0, null, this);
// Get the launch Intent
parseIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
parseIntent(getIntent());
}
private void parseIntent(Intent intent) {
// If the Activity was started to service a Search request, extract the search query.
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String searchQuery = intent.getStringExtra(SearchManager.QUERY);
// Perform the search
performSearch(searchQuery);
}
}
// Execute the search.
private void performSearch(String query) {
// Pass the search query as an argument to the Cursor Loader
Bundle args = new Bundle();
args.putString(QUERY_EXTRA_KEY, query);
// Restart the Cursor Loader to execute the new query.
getLoaderManager().restartLoader(0, args, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String query = “0”;
// Extract the search query from the arguments.
if (args != null)
query = args.getString(QUERY_EXTRA_KEY);
// Construct the new query in the form of a Cursor Loader.
String[] projection = {MyContentProvider.KEY_ID, MyContentProvider.KEY_COLUMN_1_NAME};
String where = MyContentProvider.KEY_COLUMN_1_NAME + “ LIKE \”%” + query + “%\””;
String[] whereArgs = null;
String sortOrder = MyContentProvider.KEY_COLUMN_1_NAME + “ COLLATE LOCALIZED ASC”;
// Create the new Cursor loader.
return new CursorLoader(this, MyContentProvider.CONTENT_URI, projection, where, whereArgs, sortOrder);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// Replace the result Cursor displayed by the Cursor Adapter with the new result set.
adapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> loader) {
// Remove the existing result Cursor from the List Adapter.
adapter.swapCursor(null);
}
}
大部分情况下,我们需要响应对搜索结果的click事件,因此需要重写onListItemClick方法:
@Override
protected void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Create a URI to the selected item.
Uri selectedUri = ContentUris.withAppendedId(MyContentProvider.CONTENT_URI, id);
// Create an Intent to view the selected item.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(selectedUri);
// Start an Activity to view the selected item.
startActivity(intent);
}
使用Search View Widget
Android 3.0后推出了Search View Widget以替代Search Activity。将Search View绑定到searchable activity中,首先要获取searchableInfo:
// Use the Search Manager to find the SearchableInfo related to this Activity.
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
SearchableInfo searchableInfo = searchManager.getSearchableInfo(getComponentName());
// Bind the Activity’s SearchableInfo to the Search View
SearchView searchView = (SearchView)findViewById(R.id.searchView);
searchView.setSearchableInfo(searchableInfo);
本地Android Content Provider
Android中提供了一些本地的Content Provider,包括下面这些:
- Media Store
- Browser
- Contacts Contract
- Calendar
- Call Log
使用Media Store Content Provider
MediaStore类有Audio,Video和Image子类,这些子类又有含有uri信息的子类。每个子类中uri信息是这么存储的:
- MediaStore.<mediatype>.Media.EXTERNAL_CONTENT_URI
- MediaStore.<mediatype>.Media.INTERNAL_CONTENT_URI
下面是一个示例:
// Get a Cursor over every piece of audio on the external volume,
// extracting the song title and album name.
String[] projection = new String[] {
MediaStore.Audio.AudioColumns.ALBUM,
MediaStore.Audio.AudioColumns.TITLE
};
Uri contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
// Get the index of the columns we need.
int albumIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ALBUM);
int titleIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.TITLE);
// Create an array to store the result set.
String[] result = new String[cursor.getCount()];
// Iterate over the Cursor, extracting each album name and song title.
while (cursor.moveToNext()) {
// Extract the song title.
String title = cursor.getString(titleIdx);
// Extract the album name.
String album = cursor.getString(albumIdx);
result[cursor.getPosition()] = title + “ (“ + album + “)”;
}
// Close the Cursor.
cursor.close();
使用Contacts Contract Content Provider
Contacts Contract Provider使用三层模型存储数据:
Android 4 学习(18):搜索的更多相关文章
- Android Animation学习(二) ApiDemos解析:基本Animatiors使用
Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...
- Android:学习AIDL,这一篇文章就够了(下)
前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...
- Android WiFiDirect 学习(二)——Service Discovery
Service Discovery 简介 在Android WifiDirect学习(一 )中,简单介绍了如何使用WifiDirect进行搜索——连接——传输. 这样会有一个问题,那就是你会搜索到到附 ...
- Android 数字签名学习笔记
Android 数字签名学习笔记 在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个permission的pro ...
- Android 布局学习之——Layout(布局)具体解释二(常见布局和布局參数)
[Android布局学习系列] 1.Android 布局学习之--Layout(布局)具体解释一 2.Android 布局学习之--Layout(布局)具体解释二(常见布局和布局參数) ...
- 我的Android 4 学习系列之数据库和Content Provider
目录 创建数据库和使用SQLite 使用Content Provider.Cusor和Content Value来存储.共享和使用应用程序数据 使用Cursor Loader异步查询Content P ...
- 我的Android 4 学习系列之文件、保存状态和首选项
目录 使用Shared Preference 保留简单的应用程序数据 保存回话间的Activity实例数据 管理应用程序首选项和创建Preference Screen 保存并加载文件以及管理本地文件系 ...
- Android 自定义支持快速搜索筛选的选择控件(一)
Android 自定义支持快速搜索筛选的选择控件 项目中遇到选择控件选项过多,需要快速查找匹配的情况. 做了简单的Demo,效果图如下: 源码地址:https://github.com/whieenz ...
- Android JNI学习(四)——JNI的常用方法的中文API
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
随机推荐
- 从客户端中检测到有潜在危险的 Request.Form 值的问题的解决方法。
在controller控制器里面添加[ValidateInput(false)] [ValidateInput(false)] public ActionResult m ...
- [svn]显示日志很慢 点击文件查看更改记录也贼慢
特此记录,防止以后忘记. 解决办法: 在 C:\Windows\System32\drivers\etc (win7) 中加入 即可 亦或将代码的url中pc名字改为ip地址也可以解决问题 对文件夹点 ...
- windows中的oracle12SE后启动的系统服务的列表
下图是我安装在windows 10下安装好oracle12.10SE之后的启动的系统服务的列表. 通常,我是将其全部修改为手动启动.当需要用oracle服务的时候,只需要启动对应的实例的服务和tnsl ...
- 通过Excel生成批量SQL语句,处理大量数据的好办法
我们经常会遇到这样的要求:用户给发过来一些数据,要我们直接给存放到数据库里面,有的是Insert,有的是Update等等,少量的数据我们可以采取最原始的办法,也就是在SQL里面用Insert into ...
- python redis的基本使用
1.redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sor ...
- SpringMvc的上传和下载
第一步:配置文件加入上传和下载的<bean>全部配置文件参考上上篇博文 <!-- 配置springMVC上传文件和下载文件 --> <bean id="mult ...
- lapis http verb 处理
1. 同一个url 包含不同的请求(respond_to 进行解决) // 路由格式 match ,通过respond_to 进行实际的http verb 处理 local lapis = requ ...
- [深度学习]Python/Theano实现逻辑回归网络的代码分析
2014-07-21 10:28:34 首先PO上主要Python代码(2.7), 这个代码在Deep Learning上可以找到. # allocate symbolic variables for ...
- linux查找目录下的所有文件中是否含有某个字符串 (转)
查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM" 查找目录下的所有文件中是否含有某个字符串,并且只打印出文件名 find .|xar ...
- 军哥 LNMP 常见问题
安装memcached出错: Install memcached...Notice: memcached-1.4.25.tar.gz not found!!!download now...--2016 ...