編輯:關於Android編程
在我們的應用程序中經常需要提供搜索服務,比如搜索聯系人, 搜索商品信息等等。我們可以自己在布局中自定義我們的搜索框,實現我們的搜索邏輯。但是還有一種更簡單的方法:使用android系統給我們提供的搜索功能框架。
在android中,提供兩種實現搜索功能的方式:search dialog 和 searchView.
search dialog類似於普通的dialog,懸浮於我們的窗體之上。示例圖如下:
searchView通常被嵌套在我們的布局之中,最典型的案例就是在actionBar中使用searchView.下圖是searchView在微信中的使用。(PS:圖中的放大鏡就是searchView)
不管你使用哪種方式,安卓系統都會發送查詢請求到處理搜索邏輯的activity中,來實現搜索功能。
另外,除了普通的文字搜索外,還提供了一下的搜索功能:
1.語音搜索
2.最近搜索記錄提示
3.自定義搜索記錄提示
4.google系統搜索框
vcq9oaM8L3A+DQo8aDIgaWQ9"基本原理">基本原理
首先我們來了解一下系統搜索功能的基本原理。
(一)當用戶在搜索框中執行搜索操作後,系統會自動創建一個Intent,並且將用戶搜索的關鍵字存放到Intent中。
(二)系統會啟動處理搜索邏輯的activity(通常可以命名為SearchableActivity)並將intent傳遞給SearchableActivity,然後在SearchableActivity中處理我們的搜索邏輯。
第一步,我們需要配置我們搜索框的xml文件,其中包括一些屬性比如:語音搜索,搜索提示和搜索記錄等等。
配置文件通常命名為searchable.xml 並且必須 存放在我們工程的res/xml目錄中(沒有就創建一個)
(PS:系統使用這個配置文件來實例化SearchableInfo對象,這個對象是提供搜索相關的元數據的,比如SearchableActivity的類名,搜索關鍵字的類型等等。但是我們不能自己實例化SearchableInfo 對象,只能通過配置文件的方式來設置)
下面是searchable.xml配置文件的內容
searchable.xml
配置文件的根節點必須是searchable ,其中label是必須的,它的值為一個string資源引用,通常是應用程序的名稱(盡管它是一個必須的屬性,但通常情況下是不顯示出來的,除非你開啟了搜索建議功能)。
android:hint是配置搜索框的輸入提示信息,雖然不是必須的屬性,但是強烈建議設置這個屬性,以便用戶輸入搜索信息的時候,可是知道能輸入那些搜索信息。
以配置很多的屬性,但大部分屬性都只是在使用搜索建議和語音搜索時進行配置。
第二步, 我們創建SearchableActivity來處理搜索邏輯並且顯示搜索結果。
我們需要在android-manifest.xml文件中配置SearchableActivity的一些屬性,來將它指定為處理搜索邏輯的activity
android-manifest.xml
...
首先在intent-filter節點中添加 ACTION_SEARCH的action。然後再meta-data節點中的name屬性必須為android.app.searchable,resource屬性為我們的配置文件searchable.xml
注意:我們並不需要在intent-filter中配置category,因為SearchManager會根據SearchableActivity的componentName,顯示地傳遞數據給它。
查看下列SearchManager.class的源碼,我們可以知道這是怎麼實現的。
SearchManager.class
/**
* Starts the global search activity.
*/
/* package */ void startGlobalSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, Rect sourceBounds) {
//這是我們的searchableActivity
ComponentName globalSearchActivity = getGlobalSearchActivity();
if (globalSearchActivity == null) {
Log.w(TAG, No global search activity found.);
return;
}
Intent intent = new Intent(INTENT_ACTION_GLOBAL_SEARCH);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//顯示傳遞
intent.setComponent(globalSearchActivity);
// Make sure that we have a Bundle to put source in
if (appSearchData == null) {
appSearchData = new Bundle();
} else {
appSearchData = new Bundle(appSearchData);
}
// Set source to package name of app that starts global search, if not set already.
if (!appSearchData.containsKey(source)) {
appSearchData.putString(source, mContext.getPackageName());
}
//查詢的數據
intent.putExtra(APP_DATA, appSearchData);
if (!TextUtils.isEmpty(initialQuery)) {
intent.putExtra(QUERY, initialQuery);
}
if (selectInitialQuery) {
intent.putExtra(EXTRA_SELECT_QUERY, selectInitialQuery);
}
intent.setSourceBounds(sourceBounds);
try {
if (DBG) Log.d(TAG, Starting global search: + intent.toUri(0));
mContext.startActivity(intent);
} catch (ActivityNotFoundException ex) {
Log.e(TAG, Global search activity not found: + globalSearchActivity);
}
}
一般而言,查詢到的數據都是通過一個ListView來展示的,所以,我們可以讓SearchableActivity繼承ListActivity來方便操作。
在SearchableActivity中,我們需要完成三件事:
1.接受查詢參數
當用戶執行搜索操作的時候,系統通過intent傳遞名為QUERY 的數據,其中包含的就是我們的搜索關鍵字,我們可以在intent中接受QUERY數據
。
public class SearchActivity extends ListActivity
{
//測試數據
private String[][] datas = { { activity, actionbar, animation, android },
{ bundle, block, bluetooth, boolean } };
//查詢結果
private String[] result;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
intent = getIntent();
// 判斷是否是搜索請求
if (Intent.ACTION_SEARCH.equals(intent.getAction()))
{
// 獲取搜索的查詢內容(關鍵字)
String query = intent.getStringExtra(SearchManager.QUERY);
2.根據查詢參數查詢數據
獲取到查詢關鍵字query後,我們就可以執行我們的查詢邏輯了。
// 執行相應的查詢動作
boolean isSuccess =queryContact(query);
private boolean queryContact(String query)
{
for (String[] ss : datas)
{
for (String s : ss)
{
if (s.contains(query)){
result = ss;
return true;
}
}
}
return false;
}
queryContact方法是我寫的模擬查詢字典的方法。這裡可以換成在數據庫或者網絡中查詢數據。
3.顯示查詢到的數據
查詢到數據中,我們需要將數據顯示到ListView中,並且當用戶點擊某一查詢結果時,將查詢結果返回給MainActivity.
intent = new Intent(SearchActivity.this, MainActivity.class);
if(isSuccess){
setListAdapter(new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, result));
getListView().setOnItemClickListener( new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView parent, View view,
int position, long id)
{
intent.putExtra(name, result[position]);
startActivity(intent);
}
});
}else{
Toast.makeText(this, 沒有查詢到數據, Toast.LENGTH_SHORT).show();
startActivity(intent);
}
}
}
最後,我們就需要在MainActivity中使用我們的搜索框了。由於前面說過,搜索框默認情況下是隱藏的,需要我們自己來調用。在調用之前,我們還需要在manifest文件中進行配置,指定使用searchableActivity.
在MianActivity的節點中,我們需要配置meta-data節點,name必須指定為android.app.default_searchable,value表示我們的searchableActivity.
如果想將搜索框指定為全局的,在整個application中都能使用,那就將meta-data節點配置在application節點中。
最後,我們在MainActivity中調用搜索框。
由於不同的設備的物理按鍵有很大的差異,有些手機有物理的搜索按鍵,而有些手機是沒有的。所以我們最好自己在activity中通過一個搜索按鈕來顯式的調用搜索框。另外一種方法是,通過手機軟鍵盤上面的搜索按鈕來調用搜索框,這需要在OnCreate()中調用 setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL) .
搜索框是一個懸浮於屏幕上的dialog。它不會對activity棧和生命周期引起任何變化。所以當搜索框出現的時候,沒有任何如onPause()的方法被調用。
通過調用onSearchRequested()方法,我們來激活搜索框。
在MainActivity中,我們點擊button來顯示搜索框,執行搜索後,將獲取到的搜索結果顯示在TextView中。
MainActivity.class
public class MainActivity extends ActionBarActivity
{
private TextView msg;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
msg=(TextView) findViewById(R.id.msg);
}
@Override
protected void onResume()
{
String name =(String) getIntent().getStringExtra(name);
if(name!=null)
msg.setText(name);
super.onResume();
}
public void search(View view)
{
onSearchRequested();
}
}
另外,我們也可以重寫onSearchRequested()方法,在搜索的同時做一些其他的操作,比如暫停音樂播放等等。
@Override
public boolean onSearchRequested() {
pauseMusic();
return super.onSearchRequested();
}
另外,如果我們需要對查詢關鍵字加一些限制條件的時候,我們可以調用onSearchRequested()發送一些額外的數據給searchableActivity,searchableActivity中進行處理。
@Override
public boolean onSearchRequested() {
//查詢參數
Bundle appData = new Bundle();
appData.putBoolean(SearchableActivity.JARGON, true);
startSearch(null, false, appData, false);
return true;
}
當searchableActivity接受到傳遞的查詢參數和關鍵字時,就可以進行查詢操作了。
//通過SearchManager.APP_DATA來提取數據
Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
if (appData != null) {
boolean jargon = appData.getBoolean(SearchableActivity.JARGON);
//下面這一句表示我們可以進行的操作。。。。
// “select * from ... where word=query and ...=jargon”;
}
注意:我們不能再onSearchRequested()方法外調用startSearch方法,任何操作都必須通過onSearchRequested()來調用。
Android的啟動過程是從init開始的,它是所有後續進程的祖進程。系統啟動的過程可以大致分為以下幾個步驟1,init.c的啟動 掛載目錄 初始化 解析配置文件2
Adapter常用的實現方式ArrayAdapter、simpleAdapter、SimpleCursorAdapter、BaseAdapter。 1、ArrayAdap
目前小米手機最新的系統為MIUI 6,相信米粉們對MIUI6都非常熟悉。你是否知道,這系統支持這音量鍵喚醒,那麼要如何去開啟這音量鍵喚醒呢?下面就一起來看看
onTach介紹ontach是Android系統中整個事件機制的基礎。Android中的其他事件,如onClick、onLongClick等都是以onTach為基礎的。o