Android 中的 Searchable 使用,及删除记录
来源:互联网 发布:mac怎么远程协助 编辑:程序博客网 时间:2024/06/04 20:09
Android为程序的搜索功能提供了统一的搜索接口,search dialog和search widget,这里简单介绍search dialog使用。search dialog 只能为于activity窗口的上方。下面以点击EditText输入框启动search dialog搜索框为例,效果如下:
该效果是在点击 EditText 时,自动跳转到 google 自带的搜索框界面。 google 自带的搜索框,其左边的图标为该 app 的图标。无论是点击该图标或者是该图标前面的箭头都是可以回到 EditText 所在的界面。
由于点击 EditText 会自动跳转界面,所以可以在跳转后的界面中自行布局,丰富界面。而本例是为了让其在当前界面实现跳转搜索,不需要额外的启动一个界面。所以在启动模式中使用“单顶模式”,即:singleTop 模式。一定要注意 google 自带的搜索框是位于 Activity 的顶部的(没办法修改)。
实现效果图中的大致步骤:
1. 在 res/xml目录下新建 searchable.xml 文件:
<span style="font-size:18px;"><?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></span>
注意:在新建 searchable.xml 时,带上后缀名。上面的代码是最简单的搜索配置代码,其中的 android:lable="@string/app_name" 必须要有,且 lable 的属性一定要为 @string/app_name。 hint 属性是提示的信息,不是必须的,这点和 EditText 类似。其他的属性可以参考 google 的官方文档。
2. 在 AndroidManifest.xml 中声明搜索的 Activity。
由于本例不需要在搜索时启动一个 Activity 所以,将其设置为 singleTop 模式。所以:
<span style="font-size:18px;"><meta-data android:name="android.app.default_searchable" android:value=".MainActivity"/></span>
在 activity 根标签内添加(因为启动模式为 singleTop 不会加载其他的界面,所以需要在 activity 标签内,如果需要在其他界面显示,则将其添加到注册该节目的 activity 根标签内):
<span style="font-size:18px;"><intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /></span>
其中的 intent-filter 标签的 name 值必须为 android.intent.action.SEARCH,meta-data标签的 resource 值为 res/xml目录下的searchable.xml 文件;
<span style="font-size:18px;">@Overridepublic boolean onSearchRequested() { //做其他的事 doOther(); return super.onSearchRequested();}</span>
<span style="font-size:18px;"> public boolean onSearchRequested() { Bundle data = new Bundle(); data.putString("key", "your info"); startSearch(null, true, data , false); return true; }</span>
<span style="font-size:18px;"> /** * 由于 Activity 的启动模式为 singleTop ,搜索的 Action 必须为: * android.intent.action.SEARCH,所以需要重写该方法,以便获取 Action 的“动作”。 * 如果不重写,Action 的返回值为 android.intent.action.MAIN */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // 设置 intent 这样就能得到正确的 Action 了 setIntent(intent); } /** * 该方法在 onNewIntent() 方法后执行,可以获取 onNewIntent() 方法设置的 intent, * 也可以直接 onNewIntent() 方法进行得到 intent 等的操作 */ @Override protected void onResume() { super.onResume(); Intent intent = getIntent(); if (intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); searchQurey(query, intent); } }</span>
<span style="font-size:18px;">package com.crazy.gemi.ui.cheaper;import android.content.SearchRecentSuggestionsProvider;import android.database.Cursor;import android.database.MatrixCursor;import android.net.Uri;import android.os.CancellationSignal;import com.crazy.gemi.R;/** * 该类用于记录最近的搜索,并将其存入数据库 */public class SearchSuggestionSampleProvider extends SearchRecentSuggestionsProvider { public final static String AUTHORITY="com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider"; public final static int MODE=DATABASE_MODE_QUERIES; public SearchSuggestionSampleProvider(){ super(); setupSuggestions(AUTHORITY, MODE); }}</span>
<span style="font-size:18px;"> <provider android:authorities="com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider" android:name=".ui.cheaper.SearchSuggestionSampleProvider"/></span>
这样就完成了所有在 AndroidManifest.xml 中的工作,其中的完整代码如下:
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.crazy.gemi"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@mipmap/naryou_logo" android:name=".ui.utils.MyApplication" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="android.app.default_searchable" android:value=".MainActivity"/> <activity android:name=".MainActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity> <provider android:authorities="com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider" android:name=".ui.cheaper.SearchSuggestionSampleProvider"/> </application> </manifest></span>
<span style="font-size:18px;">android:searchSuggestAuthority="com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider" android:searchSuggestSelection=" ? "</span>
<span style="font-size:18px;"><?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" android:searchSuggestAuthority="com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider" android:searchSuggestSelection=" ? "></searchable></span>
<span style="font-size:18px;"> private void searchQurey(String query , Intent intent) { //保存搜索记录 SearchRecentSuggestions suggestions=new SearchRecentSuggestions(this, SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE); suggestions.saveRecentQuery(query, null); }</span>
<span style="font-size:18px;">package com.crazy.gemi.ui.cheaper;import android.content.SearchRecentSuggestionsProvider;import android.database.Cursor;import android.database.MatrixCursor;import android.net.Uri;import android.os.CancellationSignal;import com.crazy.gemi.R;/** * 该类用于记录最近的搜索,并将其存入数据库 */public class SearchSuggestionSampleProvider extends SearchRecentSuggestionsProvider { public final static String AUTHORITY="com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider"; public final static int MODE=DATABASE_MODE_QUERIES; public SearchSuggestionSampleProvider(){ super(); setupSuggestions(AUTHORITY, MODE); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { String[] items = null; Cursor cursor = super.query(uri, projection, selection, selectionArgs, sortOrder); int arrayLength = cursor.getCount(); if (arrayLength != 0) { items = new String[arrayLength + 1]; cursor.moveToFirst(); int i = 0; for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { int number = cursor.getColumnIndex("suggest_intent_query"); items[i] = cursor.getString(number); i++; } // items[i] = "清空历史记录"; items[i] = getContext().getString(R.string.clear_search_keyword); }else { return null; } // suggest_format 等字段不能够改变 String[] columns = new String[]{"suggest_format", "suggest_text_1", "suggest_intent_query", "_id"}; // ContentProvider对外共享数据的时候,如果没有数据库,需要对外共享数据时则使用 MatrixCursor MatrixCursor stringCursor = new MatrixCursor(columns); String row[] = new String[4]; int i = 0; for (CharSequence item : items) { row[0] = "" + 0; row[1] = item.toString(); row[2] = item.toString(); row[3] = "" + (++i); stringCursor.addRow(row); } return stringCursor; }}</span>
这样是不是就可以实现删除功能了呢?如果按照上面的步骤去执行,那就会看见当我们每次点击“删除历史记录”时,就会在搜索框中多出“删除历史记录”这个字眼。由此可以我们并没有实现该功能,只实现了添加“删除历史记录”字眼的功能。到这一步离实现“删除历史记录”只有一步之遥的距离了。执行在 searchQurey() 方法中添加如下代码即可:
<span style="font-size:18px;"> // 点击 “清空历史记录” 删除记录 if(query.equals(getString(R.string.clear_search_keyword))){ suggestions.clearHistory(); }else{ suggestions.saveRecentQuery(query, null); }</span>
完整的 MainActivity.java 代码如下:
<span style="font-size:18px;">package com.crazy.gemi;import android.app.SearchManager;import android.content.Intent;import android.graphics.Color;import android.provider.SearchRecentSuggestions;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.os.Bundle;import android.support.v4.app.FragmentTransaction;import android.view.View;import android.widget.TextView;import com.crazy.gemi.ui.cheaper.CheaperFragment;import com.crazy.gemi.ui.cheaper.SearchSuggestionSampleProvider;import com.crazy.gemi.ui.favor.FavorFragment;import com.crazy.gemi.ui.more.MoreFragment;import com.crazy.gemi.ui.near.NearFragment;import com.crazy.gemi.ui.pocket.PocketFragment;public class MainActivity extends FragmentActivity implements View.OnClickListener, CheaperFragment.SearchResult{ private TextView[] textView = new TextView[5]; private View[] views = new View[5]; // 其中的 firstFragment 相当于是个中间变量 private Fragment firstFragment, nearFragment, cheaperFragment, favorFragment, pocketFragmnet, moreFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); initFragment(); } private void init() { textView[0] = (TextView)findViewById(R.id.near); textView[1] = (TextView)findViewById(R.id.search_cheaper); textView[2] = (TextView)findViewById(R.id.favor); textView[3] = (TextView)findViewById(R.id.pocket); textView[4] = (TextView)findViewById(R.id.more); views[0] = findViewById(R.id.near_top_line); views[1] = findViewById(R.id.cheaper_top_line); views[2] = findViewById(R.id.favor_top_line); views[3] = findViewById(R.id.pocket_top_line); views[4] = findViewById(R.id.more_top_line); textView[0].setOnClickListener(this); textView[1].setOnClickListener(this); textView[2].setOnClickListener(this); textView[3].setOnClickListener(this); textView[4].setOnClickListener(this); } private void initFragment() { firstFragment = FavorFragment.newInstance(); favorFragment = firstFragment; // 最先加载的 fragment getSupportFragmentManager().beginTransaction(). add(R.id.frame_layout, favorFragment).commit(); textView[2].setTextColor(Color.BLACK); views[2].setBackgroundColor(Color.parseColor("#FF6600")); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.near:// getSupportFragmentManager().beginTransaction().// replace(R.id.frame_layout, NearFragment.newInstance()).commit(); if(nearFragment==null){ nearFragment= NearFragment.newInstance(); } switchContent(firstFragment, nearFragment, getSupportFragmentManager().beginTransaction()); firstFragment = nearFragment; selectStringAndBackgroundColor(0); break; case R.id.search_cheaper: if(cheaperFragment==null){ cheaperFragment= CheaperFragment.newInstance(); } switchContent(firstFragment, cheaperFragment, getSupportFragmentManager().beginTransaction()); firstFragment = cheaperFragment; selectStringAndBackgroundColor(1); break; case R.id.favor: if(favorFragment==null){ favorFragment= FavorFragment.newInstance(); } switchContent(firstFragment, favorFragment, getSupportFragmentManager().beginTransaction()); firstFragment = favorFragment; selectStringAndBackgroundColor(2); break; case R.id.pocket: if(pocketFragmnet==null){ pocketFragmnet= PocketFragment.newInstance(); } switchContent(firstFragment, pocketFragmnet, getSupportFragmentManager().beginTransaction()); firstFragment = pocketFragmnet; selectStringAndBackgroundColor(3); break; case R.id.more: if(moreFragment==null){ moreFragment= MoreFragment.newInstance(); } switchContent(firstFragment, moreFragment, getSupportFragmentManager().beginTransaction()); firstFragment = moreFragment; selectStringAndBackgroundColor(4); break; } } /** * 通过 position 的位置改变文字和 View 的颜色 * @param position */ private void selectStringAndBackgroundColor(int position){ int sum = textView.length; for (int i = 0; i < sum; i++) { if (position == i) { textView[i].setTextColor(Color.BLACK); views[i].setBackgroundColor(Color.parseColor("#FF6600")); } else { textView[i].setTextColor(Color.GRAY); views[i].setBackgroundColor(Color.parseColor("#f0f0f0")); } } } /** * 判断是否添加了界面,以保存当前状态 */ public void switchContent(Fragment from, Fragment to, FragmentTransaction transaction) { if (!to.isAdded()) { // 先判断是否被add过 transaction.hide(from).add(R.id.frame_layout, to) .commit(); // 隐藏当前的fragment,add下一个到Activity中 } else { transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个 } } /** * 由于 Activity 的启动模式为 singleTop ,搜索的 Action 必须为: * android.intent.action.SEARCH,所以需要重写该方法,以便获取 Action 的“动作”。 * 如果不重写,Action 的返回值为 android.intent.action.MAIN */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // 设置 intent 这样就能得到正确的 Action 了 setIntent(intent); } /** * 该方法在 onNewIntent() 方法后执行,可以获取 onNewIntent() 方法设置的 intent, * 也可以直接 onNewIntent() 方法进行得到 intent 等的操作 */ @Override protected void onResume() { super.onResume(); Intent intent = getIntent(); if (intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); searchQurey(query, intent); } } @Override public void doSearch() { onSearchRequested(); } private void searchQurey(String query , Intent intent) { //保存搜索记录 SearchRecentSuggestions suggestions=new SearchRecentSuggestions(this, SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE); // 点击 “清空历史记录” 删除记录 if(query.equals(getString(R.string.clear_search_keyword))){ suggestions.clearHistory(); }else{ suggestions.saveRecentQuery(query, null); } }// private void clearSearchHistory() {// SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,// SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE);// suggestions.clearHistory();// }}</span>
- Android 中的 Searchable 使用,及删除记录
- Android Searchable
- Android 浮动搜索框 searchable 使用
- Android之Searchable
- android - Searchable Configuration
- grails searchable 使用
- searchable
- android XML下searchable.xml
- Android API Guides---Searchable Configuration
- 只使用一条sql语句,删除表中的重复记录
- Android Studio 使用中的相关“Bug”记录
- VB之旅-删除FlexGridLevel中选中的行及表中的记录
- android中Creating a Searchable Activity
- Android 浮动搜索框 searchable 使用指南
- Android 如何修改默认的searchable items。
- Android 浮动搜索框 searchable 使用指南
- android如何修改默认的searchable items.
- Android TV -3.2- Making TV Apps Searchable
- 排序整理
- 3/4-3/6 js
- 欢迎使用CSDN-markdown编辑器
- 线性表
- [C语言]多维数组指针
- Android 中的 Searchable 使用,及删除记录
- IIS调用COM组件的权限问题
- SQL读书笔记(二)
- android线程优化
- maven学习.1
- linux 命令学习之 (nohup)
- [解决] User [dr.who] is not authorized to view the logs for application
- C#在线程池中调用委托
- [LeetCode]104. Maximum Depth of Binary Tree