如何捕获SearchView的清除按钮点击事件?

87

我如何捕获用户单击清除SearchView文本的事件,通过单击右侧的X按钮?

我已经捕获了onQueryTextChange事件,但是这适用于任何文本更改,而不仅仅是针对那个X按钮。


我也在寻找这个问题的答案。有人有链接吗?因为我在谷歌上搜索了几个小时,但什么都没找到。 - Sitram
13个回答

118
尝试了许多组合后,我找到了如何捕获SearchView中“X”按钮后面的事件。
以下是我某个应用程序中 onCreateOptionsMenu 函数的代码片段。 mSearchMenumSearchView 是全局变量。 该“X”实际上是一个具有ID search_close_btn 的ImageView,而文本区域则是具有ID search_src_text 的EditText视图。
@SuppressLint("NewApi")
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu items for use in the action bar
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.country_list_activity_actions, menu);
        mSearchMenu = menu.findItem(R.id.action_search);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // Get the SearchView and set the searchable configuration
            SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            mSearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();

            // Assumes current activity is the searchable activity
            mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
            mSearchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default

            // Get the search close button image view
            ImageView closeButton = (ImageView)mSearchView.findViewById(R.id.search_close_btn);

            // Set on click listener
            closeButton.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    LoggerUtils.d(LOG, "Search close button clicked");
                    //Find EditText view
                    EditText et = (EditText) findViewById(R.id.search_src_text);

                    //Clear the text from EditText view
                    et.setText("");

                    //Clear query
                    mSearchView.setQuery("", false);
                    //Collapse the action view
                    mSearchView.onActionViewCollapsed();
                    //Collapse the search widget
                    mSearchMenu.collapseActionView();
                }
            });
        }

        // When using the support library, the setOnActionExpandListener() method is
        // static and accepts the MenuItem object as an argument
        mSearchMenu.setOnActionExpandListener(new OnActionExpandListener() {

            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                //Nothing to do here
                LoggerUtils.d(LOG, "Search widget expand ");
                return true; // Return true to expand action view
            }

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                LoggerUtils.d(LOG, "Search widget colapsed ");
                return true; // Return true to collapse action view
            }
        });

        return super.onCreateOptionsMenu(menu);
    }

我这里有一个类似的问题:http://stackoverflow.com/questions/43702055/android-how-do-i-get-searchview-close-button-to-return-to-search-edittext?noredirect=1#comment74449117_43702055。mSearchView.onActionViewExpanded()不起作用。你有什么想法或者建议可以解决吗? - AJW
非常有帮助。谢谢。 - Pooja

58

您可以直接使用 onCloseListener()。

sv= (SearchView) findViewById(R.id.searchView1);

sv.setOnCloseListener(new OnCloseListener() {
            @Override
            public boolean onClose() {
                Toast t = Toast.makeText(MainActivity.this, "close", Toast.LENGTH_SHORT);
                t.show();

                return false;
            }
        });

我不认为有任何不工作的原因,除非是https://dev59.com/dWYr5IYBdhLWcg3wJ2-U#14622049。 - spaceMonkey
42
也许这个方法适用于一个正在折叠的“SearchView”,但是对于我来说,在“iconifiedByDefault = false”时它并不起作用。 - Richard Le Mesurier

36

我在尝试按照ID查找组件时出现了问题,但我找到了另一种通过相同SearchView的上下文来搜索该组件的方法

// Catch event on [x] button inside search view
int searchCloseButtonId = searchView.getContext().getResources()
                .getIdentifier("android:id/search_close_btn", null, null);
ImageView closeButton = (ImageView) this.searchView.findViewById(searchCloseButtonId);
// Set on click listener
closeButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
       // Manage this event.
    }
});

3
可以,我会尽力进行翻译。以下是翻译的结果:它可以工作,只需要根据需要添加 searchView.setIconified(true);searchView.setIconified(false); 即可。 - Gidi Sprintzin
3
这看起来有点粗糙。 - Sharp Edge
3
抓住了 java.lang.NullPointerException 异常。 - Serg Burlaka

29

我使用这段代码来捕获文本查询的清除,并执行我的操作。

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search, menu);

        SearchView searchView = (SearchView) menu.findItem(R.id.search_button).getActionView();
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

        SearchView.OnQueryTextListener textChangeListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String cs) {
                if (TextUtils.isEmpty(cs)){
                    //Text is cleared, do your thing
                }
                return false;
            }

            @Override
            public boolean onQueryTextSubmit(String query) {
                //text query submitted
            }
        };
        searchView.setOnQueryTextListener(textChangeListener);

        return true;
    }

简单而高效。 - Alexandre Prazeres
2
我使用这种方法遇到的一个问题是,当通过单击主页/返回图标关闭搜索视图时,它似乎也会触发。在我的情况下,我需要针对这两种不同的操作采用不同的行为。 - user1689757
太棒了,看起来正是我需要的! :) - Serg Burlaka
4
这个回答没有涉及问题的一个重要部分 - 如何区分通过点击“x”按钮清除和通过一直按退格键直到没有文本清除的区别。 - Joeleski

25
如果您使用了Appcompat库,建议改用
getResources().getIdentifier("android:id/search_close_btn", null, null);

你可以做到这一点:

MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
View closeButton = searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn);
                closeButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //handle click
                    }
                });

2019年8月修订:

如果您使用androidx,请使用:androidx.appcompat.R.id.search_close_btn


谢谢,这是唯一有效的解决方案。 - DIRTY DAVE

12

如果您正在使用androidx的SearchView,您可以这样做:

val closeButton: View? = searchView.findViewById(androidx.appcompat.R.id.search_close_btn)
closeButton?.setOnClickListener { 
    //TODO: Set your action
}

4
需要注意的是,这会覆盖清除功能。因此,您还应该调用 searchView.setQuery("", false) - djserva

6

来自 Eduardo 的解决方案对我不起作用。我找到了另一种适用于Kotlin的方法。我感谢SjoerdvGestel,他的回答帮助了我。

// Get the close button on the searchView
val closeButtonId: Int = searching.context.resources.getIdentifier("android:id/search_close_btn", null, null)
val closeButton = searching.findViewById(closeButtonId) as ImageView

// On close collapse the searchView
closeButton.setOnClickListener {
    searching.onActionViewCollapsed()
    true
}

5
    ImageView closeButton = (ImageView) this.searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn);

    closeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Manage this event.


        }
    });

请使用 R.id.search_go_btn 作为“提交”按钮。

5
一个 Kotlin 的答案:
mySearchView.setOnCloseListener(object : SearchView.OnCloseListener {
            override fun onClose(): Boolean {
                // Do your stuff
                return false
            }
        })

3

我通过检查androidx.appcompat.widget.SearchView类并查找关闭按钮的id,发现ImageView mCloseButton = findViewById(R.id.search_close_btn);。因此解决方案是在您的searchView实现中获取此id的引用并将onClick监听器附加到它上面。内部发生的事情是我们覆盖了imageView的setOnClickListener并添加了我们的实现。以下是代码。

SearchView searchView = findViewById(R.id.search_view);
ImageView closeButton = searchView.findViewById(R.id.search_close_btn);
if (closeButton != null) closeButton.setOnClickListener(v -> {
       //your logic goes in here
    });

这一定是所有答案中最简单的答案! - Prajwal Waingankar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接