首页

源码搜藏网

首页 > 开发教程 > 手机开发 >

在Android应用创建一个搜索栏

创建时间:2016-06-02 15:54  

Android SDK提供了一组API实现在应用这种模式,并在此文章中,我们将回顾落实到你的应用程序所需的第一步。

编者注

这篇文章是我们在CodeProject赞助商。这些文章旨在为您提供的产品和我们认为服务的信息,有用的开发价值和

英特尔开发人员专区提供了工具,以及如何对跨平台应用程序开发,平台和技术信息,代码示例和对专业知识的信息,以帮助开发者进行创新并取得成功。加入我们的社区的Android物联网英特尔RealSense™技术,并视窗下载工具,获取开发套件,分享创意与志同道合的开发者,并参与编程马拉松的,竞赛,路演,和当地活动。

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

在手!

让我们开始吧!创建使用“空活动”模板的Android Studio中的一个新项目。一旦项目被创建,添加新的菜单文件,并将它命名为RES /菜单/ menu_search.xml

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

我们的菜单文件只包含一个项目负责显示搜索按钮。当用户按下该按钮时,它膨胀并示出了要搜索的文本字段允许使用输入术语。负责这项任务的小部件是搜索查看,因为我们可以在看到应用程序:actionViewClass属性。定义应用程序:showAsAction与价值collapseActionView允许搜索查看当按钮被窃听扩大自身。

请注意,我们使用的是支持库在这里保持在Android版本的兼容性。

一旦我们创建了一个菜单文件,我们将其加载到MainActivity像描述如下:

隐藏   缩小 在Android应用创建一个搜索栏   复制代码
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;
    }
}

内部onCreateOptionsMenu()我们使用加载菜单资源文件膨胀() 通过菜单对象,我们发现该菜单项包含搜索查看小部件。一个设置OnQueryTextListener对象到搜索查看我们的应用程序能够检测两个事件:

所以,你可以实现任何你在这些方法中要执行搜索(访问SQLite数据库或Web服务,例如)。而已!这是为了实现你的应用程序搜索功能,最简单的方法。

改善搜索体验

以前的方法工作得很好,但一般需要一个搜索操作,以帮助用户找到他们想要的东西。要做到这一点的一个好方法是显示在用户输入一些建议。为了证明这种方法,我们将展示城市的名单,而用户键入全市名称搜索查看这个列表被存储在服务器中。我们要做的第一件事情就是创建一个可搜索的配置。于是,一个新的文件添加到项目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"/>

让我们来了解这个文件中定义的属性:

正如我们所知,内容提供商通常访问SQLite数据库来存储和检索数据,但我们可以用它来访问网络也是如此,Android文档清清楚楚地写着:

内容提供商“可以从多个线程同时被调用,并且必须是线程安全的。”

在本实施例中,建议将从存储在web服务器JSON文件进行检索。创建一个新的内容提供商将其命名为CitySuggestionProvider,只是执行查询() 其他都是空的):

隐藏   缩小 在Android应用创建一个搜索栏   复制代码
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.com/u/6802536/cidades.json")
                    .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象下面这样调用。内容://ngvl.android.demosearch.citysuggestion/search_suggest_query/santos上限= 50

系统调用我们的供应商加入search_suggest_query / <文本>中的URI的结尾。结果的上限设置为50默认情况下,它作为查询参数传递。值得注意的是,搜索操作UI线程之外完成所以像我们这样做,我们可以执行HTTP请求是很重要的。在这个例子中,我们存储了全市内存列表,但在实践中,我们可以在我们的SQLite数据库使用的表。

使用开放的对象,我们已经得到了使用文本参数getLastPathSegment()的建议,使用退回,最大数getQueryParameter() 阅读从网络内容后,MatrixCursor建代表建议的城市名单。这里一个重要的细节是列名。列“_id”和“suggest_text_1”是强制性的。您可以使用更多的列或创建光标适配器的子类来定制您的建议名单。

正如我之前说的,我们的建议是存储在Web服务器上的JSON文件。所以在这里,我们正在执行的请求来检索城市名单和阅读它作为使用OkHttp库中的JSON文件。所以,不要忘记添加了这种依赖的build.gradle文件:

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

一定要添加INTERNET权限在AndroidManifest.xml中,内容提供商声明如下图所示:

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

使用值android.app.searchable<元数据>标签,我们正在定义的活动有一个可搜索的配置。现在,我们已将此信息提供给搜索查看部件。修改onCreateOptionsMenu()看起来像如下:

@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;
}

运行应用程序并开始输入搜索查看里面的一些文字。你会看到,一些建议显示:

在Android应用创建一个搜索栏

太好了!我们的建议功能工作正常。但是,当选择了一个建议,会发生什么?或者,如果我按在键盘搜索按钮?

处理建议和搜索行动

在这个时刻,当用户按下搜索按钮或选择列表中的一个建议,创建并显示在MainActivity的新实例。为了避免这种情况,我们可以设置我们的活动的启动模式singleTopAndroidManifest.xml中贯彻onNewIntentMethod() 

<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();
    }
}

当用户点击搜索按钮,该活动是使用所谓的ACTION_SEARCH,但在选择时建议,使用ACTION_VIEW(如我们在搜索的配置文件中定义)。如果你现在运行应用程序并执行搜索,同样的实例MainActivity使用,而不是创建一个新的。

您可以使用这种方法没有问题,但你可以需要(或喜欢)来执行的其他活动进行搜索。为了做到这一点,我们要创建一个新的搜索活动,当用户按下搜索按钮或选择一个建议,将被调用。

它在声明中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声明。所以,现在,我们必须执行的变化不大MainActivity

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    searchView.setSearchableInfo(searchManager.getSearchableInfo(
            new ComponentName(this, SearchableActivity.class)));
    ...
}
// Remove onNewIntent method too

与此实现中,当用户按下返回/搜索键,一个新活动使用操作“开始android.intent.action.SEARCH ”和一个参数称为“ 查询 ”。该参数表示由用户键入的文本搜索查看下面的代码显示如何处理在搜索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);
        }
    }
}

一旦你有一个查询参数可以搜索任何你想要的。例如,一个本地数据库/内容提供者或Web服务。

上一篇:IOS中弹出键盘后出现fixed失效现象的解决方案
下一篇:创造一个Android的应用程序浏览器

相关内容

热门推荐