Android 操作栏 SearchView 作为自动完成?

Posted

技术标签:

【中文标题】Android 操作栏 SearchView 作为自动完成?【英文标题】:Android Action Bar SearchView as Autocomplete? 【发布时间】:2013-03-26 03:35:13 【问题描述】:

我在操作栏中使用 SearchView。我想在搜索视图上使用自动完成功能从数据库中获取结果。

这可能吗?还是我需要使用自定义文本框,然后为其添加自动完成功能?

【问题讨论】:

【参考方案1】:

所以我只需要为 v7 版本执行此操作,并且沮丧地发现我不能简单地使用 ArrayAdapter 设置适配器。

我不想使用普通的 AutoCompleteTextView(就像这里的***评论者那样),因为那样你就会错过 SearchView 的许多时髦功能,比如小搜索图标和 x 按钮。

所以我扩展了 SearchView 并得到了这个:

public class ArrayAdapterSearchView extends SearchView 

private SearchView.SearchAutoComplete mSearchAutoComplete;

public ArrayAdapterSearchView(Context context) 
    super(context);
    initialize();


public ArrayAdapterSearchView(Context context, AttributeSet attrs) 
    super(context, attrs);
    initialize();


public void initialize() 
    mSearchAutoComplete = (SearchAutoComplete) findViewById(android.support.v7.appcompat.R.id.search_src_text);
    this.setAdapter(null);
    this.setOnItemClickListener(null);


@Override
public void setSuggestionsAdapter(CursorAdapter adapter) 
    // don't let anyone touch this


public void setOnItemClickListener(OnItemClickListener listener) 
    mSearchAutoComplete.setOnItemClickListener(listener);


public void setAdapter(ArrayAdapter<?> adapter) 
    mSearchAutoComplete.setAdapter(adapter);


public void setText(String text) 
    mSearchAutoComplete.setText(text);



您可以在 ActionBar 的菜单 xml 中使用它,如下所示:

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

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_menu_add"
    android:title="TITLE"
    app:actionViewClass="com.yourpackage.ArrayAdapterSearchView"
    app:showAsAction="ifRoom|collapseActionView"/>

</menu>

您可能还想向自动完成列表添加点击功能(例如,将文本设置为 EditText):

MenuItem searchItem = menu.findItem(R.id.action_search);
final ArrayAdapterSearchView searchView = (ArrayAdapterSearchView)searchItem.getActionView();
searchView.setOnItemClickListener(new OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) 

        searchView.setText(adapter.getItem(position).toString());

    
);

这里有一个与普通旧 android.widget.SearchView 类似的版本:

public class ArrayAdapterSearchView extends SearchView 

private AutoCompleteTextView mSearchAutoComplete;

public ArrayAdapterSearchView(Context context) 
    super(context);
    initialize();


public ArrayAdapterSearchView(Context context, AttributeSet attrs) 
    super(context, attrs);
    initialize();


public void initialize() 
    mSearchAutoComplete = (AutoCompleteTextView) findViewById(getResources().getIdentifier("android:id/search_src_text", null, null));
    setAutoCompleSuggestionsAdapter(null);
    setOnItemClickListener(null);


@Override
public void setSuggestionsAdapter(CursorAdapter adapter) 
    throw new UnsupportedOperationException("Please use setAutoCompleSuggestionsAdapter(ArrayAdapter<?> adapter) instead");


public void setOnItemClickListener(AdapterView.OnItemClickListener listener) 
    mSearchAutoComplete.setOnItemClickListener(listener);


public void setAutoCompleSuggestionsAdapter(ArrayAdapter<?> adapter) 
    mSearchAutoComplete.setAdapter(adapter);


public void setText(String text) 
    mSearchAutoComplete.setText(text);



【讨论】:

我喜欢这个想法并实现了它,但是我遇到了一个问题。我可以看到我的自动完成结果,但是当我点击一个项目时,项目字符串没有被选中。我的意思是,一旦我选择它,它就不会出现在 textView 中。您能否对此提供更多见解?还是工作代码 sn-p ? 那么我必须在我的 customSearchView 类中添加一个新方法(setText)。 是的:public void setText(String text) mSearchAutoComplete.setText(text); 为什么不使用默认建议功能?喜欢这里:developer.android.com/guide/topics/search/… @vedant1811 可能是因为人们不想使用CursorAdapter【参考方案2】:

我已使用自定义 AutoCompleteTextView 并将其添加到 ActionBar。

public class MainActivity extends Activity 

    private static final String[] COUNTRIES = new String[]  "Belgium",
            "France", "France_", "Italy", "Germany", "Spain" ;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setDisplayShowCustomEnabled(true);
        // actionBar.setDisplayShowTitleEnabled(false);
        // actionBar.setIcon(R.drawable.ic_action_search);

        LayoutInflater inflator = (LayoutInflater) this
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflator.inflate(R.layout.actionbar, null);

        actionBar.setCustomView(v);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_dropdown_item_1line, COUNTRIES);
        AutoCompleteTextView textView = (AutoCompleteTextView) v
                .findViewById(R.id.editText1);
        textView.setAdapter(adapter);

    


和你的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:gravity="center" >

    <TextView
        android:id="@+id/textView1"
        android:layout_
        android:layout_
        android:text="Action Bar:"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#FFFFFF" />

    <AutoCompleteTextView
        android:id="@+id/editText1"
        android:layout_
        android:layout_
        android:ems="10"
        android:imeOptions="actionSearch"
        android:inputType="textAutoComplete|textAutoCorrect"
        android:textColor="#FFFFFF" >

        <requestFocus />
    </AutoCompleteTextView>

</LinearLayout>

已编辑:

请检查this,这个link可能对你有帮助。 code is here.

【讨论】:

如何将数据源添加为数据库?使用有限的字符串更容易。但我有近 250 个列表,还有一个列表,最多 4000 行 好的,但这不是 SearchView。当文本存在时,我实际上想要左侧的搜索图标和右侧的 X 图标。 @tasomaniac: 你想要的也不是搜索视图......无论结合上面的代码和这段代码----> ***.com/a/6355178/1168654 我解决了我的问题。实际上 SearchView 具有内置的自动完成功能,但它需要一个 contentprovider。我没有设置 AutoCompleteTextView 及其必要的功能,而是简单地创建了一个只查询不插入、删除的 ContentProvider。并且解决了。 是否可以在一个活动的同一个操作栏中添加两个搜索小部件?【参考方案3】:

这是使用CursorAdapter 的另一种方法:

ExampleActivity.java

private Menu menu;

@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean onCreateOptionsMenu(Menu menu) 

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

    this.menu = menu;

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 

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

        SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();

        search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));

        search.setOnQueryTextListener(new OnQueryTextListener()  

            @Override 
            public boolean onQueryTextChange(String query) 

                loadHistory(query);

                return true; 

             

        );

    

    return true;



// History
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void loadHistory(String query) 

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 

        Cursor cursor = db.rawQuery("SELECT * FROM items", null); // Example database query

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

        final SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();

        search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));

        search.setSuggestionsAdapter(new ExampleAdapter(this, cursor, items));

    


现在你需要创建一个扩展自CursorAdapter的适配器:

ExampleAdapter.java

public class ExampleAdapter extends CursorAdapter 

    private List<String> items;

    private TextView text;

    public ExampleAdapter(Context context, Cursor cursor, List<String> items) 

        super(context, cursor, false);

        this.items = items;

    

    @Override
    public void bindView(View view, Context context, Cursor cursor) 

        text.setText(cursor.getString(cursor.getColumnIndex("text"))); // Example column index

    

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) 

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = inflater.inflate(R.layout.item, parent, false);

        text = (TextView) view.findViewById(R.id.text);

        return view;

    


请注意:导入CursorAdapter时不要导入Android支持版本,而是导入标准android.widget.CursorAdapter

适配器还需要自定义布局:

res/layout/item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>

    <TextView
        android:id="@+id/item"
        android:layout_
        android:layout_ />

</RelativeLayout>

您现在可以通过向布局添加额外的文本或图像视图并使用适配器中的数据填充它们来自定义列表项。现在你需要一个 SearchView 菜单项:

res/menu/example.xml

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

    <item
        android:id="@+id/search"
        android:title="@string/search"
        android:showAsAction="ifRoom"
        android:actionViewClass="android.widget.SearchView" />

</menu>

然后创建一个可搜索的配置:

res/xml/searchable.xml

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/search"
    android:hint="@string/search" >
</searchable>

最后在清单文件的相关活动标签中添加这个:

AndroidManifest.xml

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

<meta-data
    android:name="android.app.default_searchable"
    android:value="com.example.ExampleActivity" />
<meta-data
    android:name="android.app.searchable"
    android:resource="@xml/searchable" />

请注意:示例中使用的@string/search 字符串应在values/strings.xml 中定义,也不要忘记为您的项目更新对com.example 的引用。

这是原始教程供参考:

http://tpbapp.com/android-development/android-action-bar-searchview-tutorial

【讨论】:

谢谢!!!成就了我的一天 :) 对我来说有一个改变,我将通过向服务器询问数据来获取数据,然后使用新的适配器更新 SearchView。会让你知道它是否有效。再次感谢! @Shirane85 嘿没问题,希望一切顺利。由于所需的游标数据格式是处理数据库数据的标准格式,因此在我看来,此方法旨在显示数据库中的结果。我在此处对其进行了调整,以便与 ArrayList 一起使用,以便通常与典型数据集更兼容,但这当然会限制性能,尤其是在处理大量数据时。 好吧,毕竟我有问题。在搜索框中填写一个字母后调用网络时,我在 onQueryTextChange 中返回 true。直到现在它都很好,什么也没有发生。但是当响应回调并且我执行 search.setSuggestionsAdapter() 时仍然没有任何反应并且建议弹出窗口没有显示。奇怪的是,在填写第二个字母后,它立即显示第一个适配器的建议。需要帮助... @Shirane85 例如当您创建静态示例列表而不是从 Web 资源加载时会发生这种情况吗?听起来您需要将其变成另一个问题并发布您的代码,因为这不会发生在我身上。如果您确实发布了问题,请从此处链接,我会尽力提供帮助。 代码有问题。如果按原样使用,它会显示奇怪(或相当陈旧)的建议。解决方案是每次都创建和设置一个新的适配器,并且总是调用 notifyDataSetChanged【参考方案4】:

我也遇到了自动完成搜索视图的这个问题,并在不使用任何额外布局和自动完成文本视图的情况下修复它,有一个名为 SearchAutoComplete 的类。我用它来实现自动完成功能,只需放置一个简单的列表适配器,其中包含一个 ArrayList 项目建议与搜索视图。将适配器设置为您的 SearchAutoComplete 和自动完成功能将在下面是我的代码。请记住,您不必添加任何自定义布局。只需用我的代码替换您的 onCreateOptionsMenu(...) 方法:

    @Override
public boolean onCreateOptionsMenu(Menu menu) 
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);

MenuItem searchItem = menu.findItem(R.id.search);
SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);

SearchAutoComplete searchAutoComplete = (SearchAutoComplete)     mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, itemArrayList);
searchAutoComplete.setAdapter(adapter);

SearchManager searchManager =
(SearchManager) getSystemService(this.SEARCH_SERVICE);
mSearchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
return true;

单击建议的项目,该项目应出现在搜索视图中,因此在 onCreateOptionmenu(...) 方法中将适配器设置为 searchAutoComplete 后添加以下代码

  searchAutoComplete.setOnItemClickListener(new OnItemClickListener() 

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) 
    // TODO Auto-generated method stub

    String searchString=(String)parent.getItemAtPosition(position);
    searchAutoComplete.setText(""+searchString);
    Toast.makeText(MainActivity.this, "you clicked "+searchString, Toast.LENGTH_LONG).show();

    
    );

【讨论】:

我试过这个,但得到了这个例外:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.SearchView$SearchAutoComplete.setTextColor(int)' on a null object reference。看来 searchAutoComplete 总是为我返回 null 。知道这是为什么吗? 嗨@HAXM...这对我有用...但是我在灰色背景中获得建议列表,如何在白色背景中获得它? @SoulRayder ,更改工具栏的主题,如果您不使用工具栏,则使用工具栏,因为不使用工具栏,您必须更改活动的主题,这将改变活动的外观【参考方案5】:

是的,这是可能的。为您的建议构建一个表(例如在 SQLiteDatabase 中)并使用所需列格式化该表。

See this link

【讨论】:

是否可以添加自动完成功能? See this 它解释了如何实现搜索视图的自动完成。【参考方案6】:

您可以通过以下方式使用 CursorAdapter 执行此操作:

MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);

searchView.setSuggestionsAdapter(adapter);

【讨论】:

【参考方案7】:
    SearchAutoComplete searchAutoComplete = mSearchView.findViewById(androidx.appcompat.R.id.search_src_text);

适用于 androidx 版本

【讨论】:

以上是关于Android 操作栏 SearchView 作为自动完成?的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 操作栏中设置 SearchView 的样式

如何更改 SearchView 上的默认图标,以便在 Android 的操作栏中使用?

更改操作栏searchview提示文本颜色

如何更改SearchView上的默认图标,以便在Android的操作栏中使用?

在操作栏中实现 SearchView

SearchView 展开后隐藏的操作栏图标