Android 4 學習(18):搜索

參考《Professional Android 4 Developmentandroid

 

搜索

經過下面這幾種方式能夠給應用程序添加搜索功能:app

  • Search Bar

  • Search View

  • Quick Search Box

可搜索的Content Provider

首先,要在res./xml目錄下建立一個xml文件,例如:ide

 

<?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通常是應用程序的名稱。ui

 

爲應用程序建立Search Activity

 

Search Activity和普通的Activity不一樣,它是一直在back stack的棧頂,每次有新的search activity建立時,不會有將其簡單的入棧,由於用戶是不會但願按返回鍵時返回本身前面的查詢結果。爲了代表該Activity能夠被搜索,須要將android.intent.action.SEARCH加入到本身的Intent Filter中,同時須要將前面建立的searchablexml文件加到meta-data標籤中:this

 

<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來處理:spa

 

@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中出來,設置方法也簡單,將下面的配置加到程序配置中就能夠了:.net

 

<meta-data android:name=」android.app.default_searchable」 android:value=」.DatabaseSkeletonSearchActivity」 />

 

使用Cursor LoaderSearch 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方法:rest

 

@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中,首先要獲取searchableInfocode

 

// 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,包括下面這些:orm

  • Media Store
  • Browser
  • Contacts Contract
  • Calendar
  • Call Log

使用Media Store Content Provider

MediaStore類有AudioVideoImage子類,這些子類又有含有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使用三層模型存儲數據:

相關文章
相關標籤/搜索