Подтвердить что ты не робот

Android SearchView.OnQueryTextListener OnQueryTextSubmit не запускается в пустой строке запроса

Я использую Android 4.1.2. У меня есть виджет SearchView на ActionBar. Документация на SearchView.OnQueryTextListener с сайта разработчика Android указывает, что onQueryTextSubmit запускается, когда "Вызывается, когда пользователь отправляет запрос. Это может быть связано с нажатием клавиши на клавиатуре или из-за нажатия кнопки отправки".

Это не происходит, если поисковый запрос пуст. Мне нужно, чтобы он запускал пустой запрос, чтобы очистить фильтр поиска ListView. Является ли это ошибкой или я что-то делаю неправильно?

4b9b3361

Ответ 1

Это не ошибка, исходный код преднамеренно проверяет пустые и пустые значения:

private void onSubmitQuery() {
    CharSequence query = mQueryTextView.getText();
    if (query != null && TextUtils.getTrimmedLength(query) > 0) {

Однако вы должны иметь возможность использовать обратный вызов OnQueryTextChange для очистки фильтров ListView, когда пользователь очищает поиск EditText.

Ответ 2

Более легкая работа: используйте onQueryTextChange, но только визуализируйте, если его пустой.

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

            @Override
            public boolean onQueryTextChange(String newText) {
                    if (searchView.getQuery().length() == 0) {
                            renderList(true);
                    }
                    return false;
            }
    });

Ответ 3

У меня была такая же проблема, и в итоге получилось следующее решение: custom SearchView + OnQueryTextListener.onQueryTextChange

Пользовательский поиск:

public class MySearchView extends SearchView {

private boolean expanded;

public MySearchView(Context context) {
    super(context);
}

@Override
public void onActionViewExpanded() {
    super.onActionViewExpanded();
    expanded = true;
}

@Override
public void onActionViewCollapsed() {
    super.onActionViewCollapsed();
    expanded = false;
}

public boolean isExpanded() {
    return expanded;
}
}

Создание действия и настройка обратного вызова:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    searchAction = menu.add(0, SEARCH_ACTION_ID, 0 , getString(R.string.action_search));
    searchAction.setShowAsAction(SHOW_AS_ACTION_ALWAYS | SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);       
    searchView = new MySearchView(getSherlockActivity());
    searchView.setOnQueryTextListener(searchQueryListener);
    searchView.setIconifiedByDefault(true);
    searchAction.setActionView(searchView);
}

И последний слушатель:

private OnQueryTextListener searchQueryListener = new OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        search(query);
        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        if (searchView.isExpanded() && TextUtils.isEmpty(newText)) {
            search("");
        }

        return true;
    }

    public void search(String query) {
        // reset loader, swap cursor, etc.
    }

};

Протестировано на АБС 4.3.

Ответ 4

У меня была такая же проблема с SearchView. Мое решение, которое состоит из стилизации SearchView, как показано в руководстве http://novoda.com/blog/styling-the-actionbar-searchview/, и установки OnEditorActionListener для EditText (как вызвать действие, когда пользователь нажал клавишу ввода?), Которое является частью SearchView было это:

final SearchView searchView = (SearchView)findViewById(R.id.search);
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
EditText searchPlate = (EditText) searchView.findViewById(searchPlateId);
searchPlate.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

        if (actionId == EditorInfo.IME_ACTION_SEARCH) {
            //Do something
        }
        return false;

    }});

Ответ 5

Как отмечали другие, это поведение преднамеренно. Я отказался от решения для OnQueryChangeListener и решил обходным путем, выполнив OnEditorActionListener в SearchView EditText, который вы можете получить при использовании R.id.search_src_text. Пока вы setImeOptions от SearchView до EditorInfo.IME_ACTION_SEARCH, вы можете обрабатывать щелчок по кнопке поиска на клавиатуре. Подробнее см. этот SO ответ.

Ответ 6

У меня была та же проблема, поскольку пустой запрос не поддерживается. Мне пришлось загрузить и использовать ActionBarSherlock, а затем изменить onSubmitQuery() метод.

Вот как выглядит мой onSubmitQuery() сейчас

private void onSubmitQuery() {
     CharSequence query = mQueryTextView.getText();
     if (query == null) {query = "";}
     if (mOnQueryChangeListener == null
             || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
         if (mSearchable != null) {
             launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
             setImeVisibility(false);
         }
         dismissSuggestions();
     }
 }

Надеюсь, что это поможет.

Ответ 7

Это очень грязный хак, однако он работает корректно, как и ожидалось, что позволяет отправить действие, даже если в SearchView не введен текст (или введенный затем отредактирован).

Он рефлексивно получает доступ к внутреннему редактору действий редактора TextView, обертывает его в пользовательский прослушиватель, где он делегирует вызов обработчику и, наконец, устанавливает его как исполнитель действия внутреннего TextView.

    Class klass = searchView.getClass();
    try {
        Field currentListenerField = klass.getDeclaredField("mOnEditorActionListener");
        currentListenerField.setAccessible(true);
        TextView.OnEditorActionListener previousListener = (TextView.OnEditorActionListener) currentListenerField.get(searchView);
        TextView.OnEditorActionListener newListener = new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (v.getText().length() == 0)
                    handleQuery("");
                return previousListener.onEditorAction(v, actionId, event);
            }
        };
        Field innerTextViewField = klass.getDeclaredField("mSearchSrcTextView");
        innerTextViewField.setAccessible(true);
        SearchView.SearchAutoComplete innerTextView = (SearchView.SearchAutoComplete) innerTextViewField.get(searchView);
        innerTextView.setOnEditorActionListener(newListener);
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }

Ответ 8

Вы не можете перезаписать это поведение. Обходной путь может заключаться в очистке фильтра, когда пользователь выходит из поиска.

Для этого вы можете использовать OnCloseListener. Однако это может также вызвать проблемы, в зависимости от минимального уровня API, для которого вы разрабатываете.

Ответ 9

Другой вариант - запустить метод onQueryTextChange вручную через TextWatcher:

public class MyActivity extends Activity implements SearchView.OnQueryTextListener, TextWatcher {

    // Basic onCreate(Bundle) here

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

        final SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
        final SearchManager manager = (SearchManager) getSystemService(SEARCH_SERVICE);
        searchView.setSearchableInfo(manager.getSearchableInfo(getComponentName()));
        searchView.setOnQueryTextListener(this);

        final int resource_edit_text = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
        ((EditText) searchView.findViewById(resource_edit_text)).addTextChangedListener(this);

        return super.onCreateOptionsMenu(menu);
    }

    // Implementation of TextWatcher, used to have a proper onQueryTextChange (it doesn't update when the last character is removed)
    @Override
    public void beforeTextChanged (final CharSequence charSequence, final int start, final int count, final int after) {}

    @Override
    public void onTextChanged (final CharSequence charSequence, final int start, final int before, final int after) {}

    @Override
    public void afterTextChanged (final Editable editable) {
        if (editable.length() == 0)
            onQueryTextChange(editable.toString());
    }

    // Implementation of OnQueryTextChangeListener

    @Override
    public boolean onQueryTextChange (final String query) {
        // do stuff
        return false;
    }

    @Override
    public boolean onQueryTextSubmit (final String query) {
        // do stuff
        return false;
    }
}

Это все идет со всеми файлами xml по умолчанию, которые были отброшены здесь, это не точка этого ответа. Это обходной путь, который я предпочитаю использовать, не стесняйтесь использовать других.

Ответ 10

Я могу сделать это просто, выполнив setOnQueryTextListener таким образом:

SearchView searchView = (SearchView) menu.findItem(R.id.searchProductView).getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            if (TextUtils.isEmpty(newText)) {
                loadLocalData(newText);
            }
            return true;
        }
    });

Где мой метод loadLocalData​​p >

//query my DB
products = ProductDAO.findByIdList(idList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
listView.setLayoutManager(layoutManager);
listView.setAdapter(<YOURADAPTER>)

Это решение очищает ваш запрос, даже если вы очищаете текст с помощью кнопки "X"

Ответ 11

В моем случае я просто хотел разрешить пользователю очищать свой запрос, поскольку он использовался как ключевое слово в поиске API, поэтому самая простая идея:

    searchView.setOnSearchClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            userQuery = "";
        }
    });

где userQuery - моя переменная, используемая для поиска и т.д.

Надеюсь, это поможет кому-то:)

Ответ 12

Это старый поток, но я нашел другое решение (код Kotlin, но работает и на Java):

override fun onQueryTextChange(newText: String?): Boolean {
            if(newText == null || newText.isEmpty())
                searchView.setQuery("\u00A0", false)
            return true
        }

\u00A0 - это символ, который выглядит как пробел, но с точки зрения кода это не так. Другими словами SearchView не является пустым. Пустая строка или " " не будут работать, потому что базовый SearchView использует обрезку, плюс пользователь может захотеть найти текст, заканчивающийся или начинающийся с пробела. Но, насколько я знаю, пользователи не могут вводить \u00A0.

Тогда все, что вам нужно сделать, это переопределить getQuery для return super.getQuery.replace("\u00A0", "") в ваш пользовательский SearchView.