Android初学者之搜索栏创建

搜索是应用于大量的Android应用程序的功能。提供一种方法来搜索您的应用程序中的内容是非常重要的,因为它可以帮助用户找到他们想要的内容。然而,这个搜索功能又必须快速,高效地获取信息,因为这可能是用户打开您的应用程序的主要原因。 Android SDK提供了一组API实现这类功能,在此文中,我们将回顾实现该应用程序所需的第一步。

首先建立一个Empty activity

<menu xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/search"

            android:title="@string/hint_search"

            android:icon="@android:drawable/ic_menu_search"

            app:showAsAction="collapseActionView|ifRoom"

            app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

创建好菜单文件后,我们将加载在MainActivity对象下面,如下所示:

public class MainActivity extends AppCompatActivity 

        implements SearchView.OnQueryTextListener {


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

    }


    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.menu_search, menu);


        MenuItem searchItem = menu.findItem(R.id.search);

        SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);

        searchView.setOnQueryTextListener(this);


        return true;

    }


    @Override

    public boolean onQueryTextSubmit(String query) {

        // User pressed the search button

        return false;

    }


    @Override

    public boolean onQueryTextChange(String newText) {

        // User changed the text

        return false;

    }
}


用户在搜索栏输入城市名称,显示城市名称列表。这个列表被存储在服务器中。我们要做的第一件事情就是创建一个搜索栏文件res/xml/searchable.xml,如下所示:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"

            android:hint="@string/hint_search"

            android:label="@string/app_name"

            android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"

            android:searchSuggestAuthority="ngvl.android.demosearch.citysuggestion"

            android:searchSuggestIntentAction="android.intent.action.VIEW"

            android:searchSuggestIntentData="content://ngvl.android.demosearch.city"/>


创建一个新的ContentProvider,并将其命名为CitySuggestionProvider,只是执行查询():

public class CitySuggestionProvider extends ContentProvider {


    List<String> cities;


    @Override

    public boolean onCreate() {

        return false;

    }


    @Override

    public Cursor query(Uri uri, String projection, String selection,

                        String selectionArgs, String sortOrder) {

        if (cities == null || cities.isEmpty()){

            OkHttpClient client = new OkHttpClient();

            Request request = new Request.Builder()

                    .url("https://dl.dropboxusercontent. ... 6quot;)

                    .build();


            try {

                Response response = client.newCall(request).execute();

                String jsonString = response.body().string();

                JSONArray jsonArray = new JSONArray(jsonString);


                cities = new ArrayList<>();


                int lenght = jsonArray.length();

                for (int i = 0; i < lenght; i++) {

                    String city = jsonArray.getString(i);

                    cities.add(city);

                }


            } catch (Exception e) {

                e.printStackTrace();

            }

        }


        MatrixCursor cursor = new MatrixCursor(

                new String {

                        BaseColumns._ID,

                        SearchManager.SUGGEST_COLUMN_TEXT_1,

                        SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID

                }

        );

        if (cities != null) {

            String query = uri.getLastPathSegment().toUpperCase();

            int limit = Integer.parseInt(uri.getQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT));


            int lenght = cities.size();

            for (int i = 0; i < lenght && cursor.getCount() < limit; i++) {

                String city = cities.get(i);

                if (city.toUpperCase().contains(query)){

                    cursor.addRow(new Object{ i, city, i });

                }

            }

        }

        return cursor;

    }


    // 

      Other methods are empty...
}


当用户开始输入文字,我们的内容提供者使用下面这样的uri。

content://ngvl.android.demosearch.citysuggestion/search_suggest_query/santos?limit=50

构建依赖性:

dependencies {

    ...

    compile 'com.squareup.okhttp3:okhttp:3.0.1'
}

一定要在AndroidManifest.xml添加INTERNET权限和ContentProvider声明,如下所示:

<manifest ...

    <uses-permission android:name="android.permission.INTERNET"/>


    <application...

        <provider

            android:name=".CitySuggestionProvider"

            android:authorities="ngvl.android.demosearch.citysuggestion"

            android:enabled="true"

            android:exported="true"/>


之后,我们还需要配置活动与搜索的连接。更改在AndroidManifest.xml活动的声明:

<activity android:name=".MainActivity">

    <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>

将信息传给SearchView widget

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.menu_search, menu);


    MenuItem searchItem = menu.findItem(R.id.search);

    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);

    searchView.setOnQueryTextListener(this);


    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

    searchView.setSearchableInfo(searchManager.getSearchableInfo(

            new ComponentName(this, MainActivity.class)));

    searchView.setIconifiedByDefault(false); 


    return true;
}



AndroidSearch_1.png


当用户按下搜索按钮或选择列表中的一个名称时,会在MainActivity中创建并显示的新实例。为了避免这种情况,我们可以在Manifest.xml设置Activity的launchMode为singleTop Android并执行onNewIntent()的方法:

<activity android:name=".MainActivity"

    android:launchMode="singleTop">
@Override
protected void onNewIntent(Intent intent) {

    super.onNewIntent(intent);

    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {

        String query = intent.getStringExtra(SearchManager.QUERY);

        Toast.makeText(this, "Searching by: "+ query, Toast.LENGTH_SHORT).show();


    } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {

        String uri = intent.getDataString();

        Toast.makeText(this, "Suggestion: "+ uri, Toast.LENGTH_SHORT).show();

    }
}

在AndroidManifest.xml中声明:

<activity android:name=".SearchableActivity">

    <intent-filter>

        <action android:name="android.intent.action.SEARCH" />

    </intent-filter>

    <meta-data android:name="android.app.searchable"

                 android:resource="@xml/searchable"/>
</activity>


记得从MainActivity声明中删除这些相同的配置。

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    ...

    searchView.setSearchableInfo(searchManager.getSearchableInfo(

            new ComponentName(this, SearchableActivity.class)));

    ...
}
// Remove onNewIntent method too


下面的代码显示在SearchableActivity中如何处理搜索:

public class SearchableActivity extends AppCompatActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_searchable);

        TextView txt = (TextView)findViewById(R.id.textView);


        Intent intent = getIntent();

        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {

            String query = intent.getStringExtra(SearchManager.QUERY);

            txt.setText("Searching by: "+ query);


        } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {

            String uri = intent.getDataString();

            txt.setText("Suggestion: "+ uri);

        }

    }
}

转载请注明本文出处: http://www.oudahe.com/p/351/