软键盘关闭时自动折叠操作栏SearchView

79

我目前正在使用ActionBar菜单项在操作栏中显示SearchView。展开搜索菜单时,软键盘被显示出来,这正是我想要的。现在,当用户按返回按钮关闭软键盘时,我也希望折叠操作栏中的SearchView。

我尝试在MenuItem和ActionView上实现OnKeyListener和OnFocusChangeListener监听器。我还尝试在Activity中使用OnBackPressed()。但以上所有方法都无法检测到使用返回按钮关闭软键盘的情况。

有任何想法吗?

我已经实现了OnActionExpandListener以知道SearchView何时可见。


这里有一个非常受欢迎的答案:https://dev59.com/vHNA5IYBdhLWcg3wC5Xh - jmishra
2
这样做并不会帮助他,他需要拦截键盘上的返回键。 - dor506
@acrespo 什么答案?你在评论一个问题... - The incredible Jan
11个回答

100

我将在 @user1258568 的回答上进行拓展,这对于懒人来说很有效。这种方法适用于我。注意,当失去焦点时会清除您的查询。

final MenuItem searchMenuItem = optionsMenu.findItem(R.id.search);
final SearchView searchView = (SearchView) searchMenuItem.getActionView();

searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean queryTextFocused) {
        if(!queryTextFocused) {
            searchMenuItem.collapseActionView();
            searchView.setQuery("", false);
        }
    }
});

1
完美运作。如果您在代码中添加了一个 SearchView,您可能需要使用 menu.getItem(yourSearchViewItemPosition) - GeeF
4
很好,在经过数小时的研究和实现后,我终于找到了你的答案 :) ... 我最初想到的是使用一个焦点监听器,但我使用了setOnFocusChangeListener()而不是setOnQueryTextFocusChangeListener()。使用你的方法一切都很好。 谢谢。 - Ionut Negru
2
@IonutNegru 不用谢!有时候一定要喜欢上 Android SDK。我想看到他们以一种明智、现代的方式重写它并放弃遗留支持,但那永远不会发生。 - Jon Willis
运行正常,很好的示例 :) - uniruddh
因为搜索视图在提交搜索时不会失去焦点,所以在我的Nexus7上无法工作。请查看我的答案。 - GaRRaPeTa
显示剩余3条评论

37

我找到了一种更好的解决方案。

searchView.setOnQueryTextFocusChangeListener(). 

OnQueryTextFocusChangeListener会在键盘显示或隐藏时调用。当搜索视图将获得焦点并且键盘首次显示时,它会被首先调用。当键盘隐藏并且搜索视图将失去焦点时,它会再次被调用,可以使用close search view来关闭搜索视图。

menuItem.collapseActionView().

6
这是具有误导性的。当键盘显示或隐藏时,OnQueryTextFocusChangeListener不会被调用。它只会在searchView获得焦点或失去焦点时被调用。因此,当第一次将SearchView设置为焦点时,将调用OnQueryTextFocusChangeListener并显示键盘。现在,如果按下返回按钮,键盘将被隐藏,但OnQueryTextFocusChangeListener不会被调用。第二次按下返回按钮时,searchView会折叠并调用OnQueryTextFocusChangeListener - faizal

11

只需要这样重写 onBackPressed:

@Override
    public void onBackPressed() {
        if (searchView.isShown()){
            searchView.onActionViewCollapsed();  //collapse your ActionView
            searchView.setQuery("",false);       //clears your query without submit
            isClosed = true;                     //needed to handle closed by back
        } else{
            super.onBackPressed();
        }
    }

你的onCreateOptionsMenu方法应该像这样填充mSearchView:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu_search, menu);
        mSearchView = (SearchView) menu.findItem(R.id.menu_action_search).getActionView();
        mSearchView.setOnQueryTextListener(this);
        mSearchView.setOnSearchClickListener(this);
        mSearchView.setOnCloseListener(this);
        isClosed = true;
        return true;
    }

你的类需要按照以下方式实现:

public class myActivity extends FragmentActivity implements
    SearchView.OnQueryTextListener, View.OnClickListener, SearchView.OnCloseListener {

你还需要以下内容:

@Override
public void onClick(View view) {
    isClosed = false;
}

@Override
public boolean onClose() {
    isClosed = true;
    return false;
}
您需要将“mSearchView”和“isClosed”都定义为该活动的全局变量。

3
根据我的经验,如果键盘弹出来了,就算调用onBackPressed方法也没有用,只会隐藏键盘,你需要再按一次返回键才能触发这个方法。我在2.3上测试过,在3.x和4.0上没试过,但我认为那里的情况应该也是一样的。 - Kevlar
@Kevlar 我认为你可能是正确的。我会再次测试并确保没有其他方法。似乎我的解决方案与他们想要的略有不同。据我所知,在软键盘显示时没有办法处理任何后退。我的解决方案肯定可以在键盘关闭后处理。将在不同的SDK上进行测试。 - Codeversed
1
我尝试使用以下代码来折叠搜索框:searchMenuItem.collapseActionView();但实际上,使用searchView.onActionViewCollapsed();才是解决方法。非常感谢! - bkurzius
我认为你不应该直接调用...函数。这些函数不是为了直接从你的代码中调用而设计的... - user457015
如何在API级别11上使用collapseActionView()函数。 - madan V
如果您使用android.support.v7.appcompat,则可以使用MenuItemCompat.collapseActionView(menuItem)来折叠操作栏中菜单搜索项。其中,menuItem是指您的操作栏菜单搜索项。 - acrespo

3

Jon Willis的回答非常好。这是对他回答的改进。

首先,创建一个实现 View.OnFocusChangeListener 接口的新类:

public class SearchViewFocusListener implements View.OnFocusChangeListener {

    private final MenuItem mMenuItem;

    public SearchViewFocusListener(MenuItem menuItem) {
        mMenuItem = menuItem;
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            mMenuItem.collapseActionView();
            if (v instanceof SearchView) {
                ((SearchView) v).setQuery("", false);
            }
        }
    }

}

接下来,在你的SearchView上设置监听器:

searchView.setOnQueryTextFocusChangeListener(new SearchViewFocusListener(menuItem));

工作得很好,但是我如何清除搜索图标的焦点?FocusChangeListener捕获设备上的Back Button按下事件,关闭软键盘并关闭SearchView,然后搜索图标出现,这正是我想要的。然而,搜索图标被突出显示(具有焦点),我希望它没有焦点。我尝试了几种清除方法,但都没有成功。有什么建议吗? - AJW

2
只需要在菜单布局中添加“collapseActionView”属性即可。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_item_search"
        android:title="@string/search"
        android:iconifiedByDefault="true"
        android:icon="@drawable/ic_action_search" 
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="ifRoom|collapseActionView"/> <--this one
</menu>

这将为您提供所需的功能。在发送查询后,请不要忘记调用SearchView上的“clearFocus”方法以关闭键盘。


1
"这可以通过以下方式实现:"
   private void setupSearchView(Menu menu) {
        final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) searchMenuItem.getActionView();

        [...]

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                searchMenuItem.collapseActionView();
                return false;
            }
            @Override
            public boolean onQueryTextChange(String newText) {
                return true;
            }
        });
    }

基于 setOnQueryTextFocusChangeListener() 的解决方案对我来说不起作用,因为事件没有被触发 - 当提交时搜索视图没有失去焦点,可能是因为我在包含搜索视图的同一个活动中执行搜索。

无论如何,我认为使用 OnQueryTextListener 更正确,因为它更精确地描述了提交文本的事件。


1

这是我为使键盘消失所做的。您可以尝试看看是否适用于您。我将searchView设置为不可见,然后再次设置为可见。

    //set query change listener
     searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
        @Override
        public boolean onQueryTextChange(String newText) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onQueryTextSubmit(String query) {
            /**
             * hides and then unhides search tab to make sure keyboard disappears when query is submitted
             */
                  searchView.setVisibility(View.INVISIBLE);
                  searchView.setVisibility(View.VISIBLE);
            return false;
        }

     });

对我也起作用了,但你必须添加 getActivity().supportInvalidateOptionsMenu(); 来恢复操作栏。 - almisoft

0
由于某些原因,menuItem.collapseActionView() 无法正常工作,因此我使用了 searchView.setIconified(true)
这将产生以下代码示例的结果。
final MenuItem searchItem = (MenuItem) menu.findItem(R.id.menu_item_search);
final SearchView searchView = (SearchView) searchItem.getActionView();

searchView.setOnQueryTextFocusChangeListener(new SearchView.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            searchView.setIconified(true);
        }
    }
});

0
如果你想要在用户点击键盘上的搜索图标时折叠键盘,可以通过简单的以下方式来实现:

在 onquerytextsubmitted 中添加:

searchView.clearfocus()

}


0

你需要调用两次 setIconified 方法。

这样才能真正折叠搜索视图并关闭键盘。
第一次调用会清除搜索视图中的文本,第二次调用会关闭键盘和搜索视图。


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