Автоматичне згортання ActionBar SearchView на закритій клавіатурі


79

Зараз я використовую пункт меню ActionBar для відображення SearchView на панелі дій. Коли елемент меню пошуку розширений, відображається програмна клавіатура, що я хочу. Тепер, коли користувач натискає кнопку "Назад", щоб закрити м'яку клавіатуру, я також хотів би згорнути SearchView на панелі дій.

Я спробував реалізувати наступні слухачі OnKeyListener та OnFocusChangeListener в MenuItem та ActionView. Я також спробував використовувати OnBackPress () в Activity. Жодне з наведеного не виявляє, коли кнопка "Назад" використовується для закриття програмної клавіатури.

Будь-які ідеї?

Я застосував OnActionExpandListener, щоб знати, коли видно SearchView.


Ось дуже популярна відповідь stackoverflow.com/questions/1109022 / ...
jmishra

2
це йому не допоможе, йому потрібно перехопити клавішу "Назад" з клавіатури
dor506,

@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

@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

Просто перевизначити onBackНаписано так:

@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
Я не думаю, що це працює; на моєму досвіді метод onBackPress не викликається, якщо клавіатура піднята; вона просто відхиляє клавіатуру, і вам потрібно ще раз натиснути назад, щоб вона викликала цей метод. Це на 2.3; Я не експериментував з 3.x та 4.0, але я підозрюю, що це теж саме там.
Кевлар,

@Kevlar Я думаю, ти можеш мати рацію. Я перевірю це ще раз і переконаюся, що немає способу. Здається, моє рішення дещо відрізняється від того, що вони хочуть. Наскільки я знаю, я не думаю, що існує спосіб обробляти будь-яку спину, поки відображається м'яка клавіатура. Моє рішення обробляє після закриття клавіатури точно. Тестуватиме на різних SDK.
Codeversed

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

Я не думаю, що вам слід звертатися безпосередньо до ... функцій. Ці функції не призначені для
виклику

як використовувати
collaPactionView

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

Вам потрібно лише поставити атрибут "collaPactionView" у макеті меню

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