Автоматическое свертывание ActionBar SearchView на Soft Keyboard закрыть


79

В настоящее время я использую элемент меню ActionBar для отображения SearchView на панели действий. Когда пункт меню поиска раскрывается, отображается мягкая клавиатура, чего я и хочу. Теперь, когда пользователь нажимает кнопку «Назад», чтобы закрыть программную клавиатуру, я также хотел бы свернуть SearchView на панели действий.

Я пробовал реализовать следующие слушатели OnKeyListener и OnFocusChangeListener в MenuItem и ActionView. Я также пробовал использовать OnBackPressed () в Activity. Ни одно из вышеперечисленных действий не определяет, когда кнопка «Назад» используется для закрытия программной клавиатуры.

Есть идеи?

Я реализовал OnActionExpandListener, чтобы знать, когда виден SearchView.


Вот очень популярный ответ stackoverflow.com/questions/1109022/…
jmishra

2
это ему не поможет, ему нужно перехватить клавишу возврата с клавиатуры
dor506 09

@acrespo Какой ответ? Вы комментируете вопрос ...
Невероятное

Ответы:


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 05

@AlexBonel Как так? Я знаю, что у S3 и S4 есть идиотские аппаратные кнопки, но я не понимаю, как это повлияет на этот фрагмент. Возможно, это потому, что меню ActionBar скрыто, а searchMenuItem действует иначе. У меня под рукой S4, надо будет это протестировать.
Джон Уиллис,

@JonWillis Если вам не сложно, не могли бы вы поделиться своим опытом такого поведения на S4?
Alex Bonel

4
Хорошо, после нескольких часов исследований и реализаций, чтобы попытаться сделать это, я нашел ваш ответ :) ... Первое, о чем я подумал, было использовать прослушиватель фокуса, но я использовал setOnFocusChangeListener()вместо него setOnQueryTextFocusChangeListener(). С вашим методом все работает нормально. Спасибо.
Ionut Negru

2
@IonutNegru пожалуйста! Иногда мне нравится Android SDK. Я хочу, чтобы они переписали его разумным, современным способом и отказались от устаревшей поддержки, но этого никогда не произойдет.
Джон Уиллис

37

Я нашел лучшее решение.

searchView.setOnQueryTextFocusChangeListener(). 

OnQueryTextFocusChangeListenerВызывается при отображении или скрытой клавиатуры. Вызывается первым, когда отображается клавиатура и фокус в представлении поиска. Вызывается снова, когда keyboardон скрыт, и вид поиска теряет фокус, close search viewзатем можно использовать

menuItem.collapseActionView().

5
Это заблуждение. 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 Думаю, ты прав. Я проверю это еще раз и убеждаюсь, что выхода нет. Кажется, мое решение немного отличается от того, что они хотят. Насколько я знаю, я не думаю, что есть способ справиться с любой проблемой, когда отображается мягкая клавиатура. Мое решение обрабатывается после закрытия клавиатуры точно. Буду тестировать на разных SDK.
Codeversed

1
я пытался свернуть поиск, используя: searchMenuItem.collapseActionView (); но оказалось, что searchView.onActionViewCollapsed (); помогли мне - спасибо!
bkurzius

Я не думаю, что вам следует напрямую обращаться к ... функциям. Эти функции не предназначены для прямого
вызова

как использовать collapseActionView () на уровне API 11.
Madan V

3

Ответ Джона Уиллиса отлично работает. Это улучшение его ответа.

Сначала создайте новый класс, который реализует 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 фиксирует нажатие кнопки «Назад» на устройстве и закрывает программную клавиатуру и закрывает 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>

Это даст вам функциональность, которую вы сами ищете. Не забудьте вызвать метод clearFocus в SearchView, чтобы закрыть клавиатуру после отправки запроса.


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

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 (), у меня не работали, потому что событие не было запущено - searchView не терял фокус при отправке, вероятно, потому, что я выполняю поиск в том же действии, которое содержит представление поиска.

Во всяком случае, я думаю, что использование OnQueryTextListener более правильно, так как оно более точно описывает событие отправки текста.


0
@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getSupportMenuInflater().inflate(R.menu.home_screen, menu);

        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        final MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
        final SearchView searchView = (SearchView) searchMenuItem
                .getActionView();
        searchView.setIconifiedByDefault(false);
        if (searchManager != null && searchView != null) {
            searchView.setSearchableInfo(searchManager
                    .getSearchableInfo(getComponentName()));

            searchView
                    .setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {

                        @Override
                        public void onFocusChange(View v, boolean hasFocus) {

                            if (!hasFocus) {
                                if (searchMenuItem != null) {
                                    searchMenuItem.collapseActionView();
                                }// end if
                                if (searchView != null) {
                                    searchView.setQuery("", false);

                                }// end if
                            }// end if

                        }
                    });

            searchView
                    .setOnQueryTextListener(new SearchView.OnQueryTextListener() {

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

                            }
                            return false;
                        }

                        @Override
                        public boolean onQueryTextChange(String newText) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                    });

        }

        return super.onCreateOptionsMenu(menu);
    }

0

Если вы хотите свернуть клавиатуру, когда пользователь щелкает значок поиска на клавиатуре, это может быть достигнуто простым

inside onquerytextsubmitted {

searchView.clearfocus()

}


0

Вам нужно дважды вызвать setIconified.

Чтобы свернуть окно поиска и закрыть клавиатуру.
При первом вызове текст окна поиска очищается, при втором вызове клавиатура и окно поиска закрывается.


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);
        }
    }
});
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.