web-dev-qa-db-ja.com

Android SearchView.OnQueryTextListener OnQueryTextSubmitは空のクエリ文字列では起動されません

Android 4.1.2を使用しています。 ActionBarにSearchViewウィジェットがあります。 Android開発者サイトのSearchView.OnQueryTextListenerに関するドキュメントには、「ユーザーがクエリを送信するときに呼び出されます。これは、キーボードのキーを押すか、送信を押すことにより、onQueryTextSubmitボタン。"

検索クエリが空の場合、これは発生しません。 ListViewの検索フィルターをクリアするために空のクエリで起動するためにこれが必要です。これはバグですか、何か間違っていますか?

25
tborja

これはバグではありません。 ソースコード は、null値と空の値に対して意図的にチェックします。

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

ただし、ユーザーが検索EditTextをクリアすると、OnQueryTextChangeコールバックを使用してListViewのフィルター可能項目をクリアできるはずです。

14
Sam

より簡単な回避策を講じる: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;
            }
    });
12
James Tan

私は同じ問題を抱えていて、次の解決策になりました: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.
    }

};

ABS 4.3でテスト済み。

10
Piotr Bazan

SearchViewでも同じ問題が発生しました。ガイドに示されているSearchViewのスタイル設定で構成される私のソリューション http://novoda.com/blog/styling-the-actionbar-searchview/ およびEditTextのOnEditorActionListenerの設定( どのようにトリガーしますかユーザーがEnterを押したときのアクション? )これは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;

    }});
9
Jan Hofman

他の人が言及したように、この動作は意図的なものです。 OnQueryChangeListenerの解決策をあきらめ、SearchViewのOnEditorActionListenerEditTextを実装することで回避策を決定しました。これはR.id.search_src_textを使用するためのハンドルを取得できます。 SearchViewのsetImeOptionsEditorInfo.IME_ACTION_SEARCHにすると、キーボードの検索ボタンのクリックを処理できます。 this SO answer を参照してください。

3
theblang

空のクエリはサポートされていないため、同じ問題が発生しました。 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();
     }
 }

お役に立てれば。

1
M3rd0n

古いスレッドですが、別の解決策を見つけました(Kotlinコードですが、Javaでも動作します):

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

_\u00A0_はスペースのように見える文字ですが、コード的にはそうではありません。つまり、SearchViewは空ではありません。空の文字列または_" "_は機能しません。これは、ベースSearchViewがトリムを使用するため、ユーザーがスペースで終わるまたはスペースで始まるテキストを検索する場合があるためです。しかし、私が知る限り、ユーザーは_\u00A0_文字を入力できません。

その後、必要なのは、カスタムSearchViewでgetQueryをreturn super.getQuery.replace("\u00A0", "")にオーバーライドすることだけです

1
Miku

これは非常にダーティなハックですただし、期待どおりに正しく動作し、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);
    }
1
samvel1024

次のように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メソッドは

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

このソリューションは、「X」ボタンでテキストをクリアしてもクエリをクリアします

0
Giuseppe Sarno

この動作を上書きすることはできません。回避策は、ユーザーが検索ビューを終了したときにフィルターをクリアすることです。

これには OnCloseListener を使用できます。ただし、開発対象の最小APIレベルによっては、これも問題を引き起こす可能性があります。

0
GeeF

私の場合、API検索でキーワードとして使用されていたため、ユーザーがクエリをクリアできるようにしたかったため、最も簡単なアイデアは次のとおりでした。

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

ここで、userQueryは検索などに使用される私の変数です。

それが誰かを助けることを願っています:)

0
Maik Martinez

もう1つのオプションは、TextWatcherを使用してonQueryTextChangeメソッドを手動でトリガーすることです。

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ファイルに当てはまりますが、この答えのポイントではありません。これは私が使用することを選択した回避策であり、他の人を自由に使用してください

0
engineercoding