【问题标题】:How to open list of search suggestions programatically?如何以编程方式打开搜索建议列表?
【发布时间】:2015-11-21 19:21:16
【问题描述】:

我的 Android 应用程序中有一个 SearchView,它可以显示对给定输入的建议。现在我想要以下行为:如果我完成键盘输入并按下软键盘上的“输入”按钮,那么我希望键盘消失,但包含搜索建议的列表应该保留。 现在的行为是,如果我输入一些字母,建议就会出现(好!)但如果我完成并按 Enter,列表就会消失(坏!)。 那么如何重新打开列表但隐藏键盘?

通常,意图 ACTION_SEARCH 会被触发并以新活动打开并显示搜索结果的方式进行处理。我只想打开带有建议的列表。

部分源码:

在 AddTeam 类的 onCreate() 中:

    SearchView searchView= (SearchView) findViewById(R.id.searchView);
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){

        @Override
        public boolean onQueryTextSubmit(String s) {
            InputMethodManager inputManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            return false;
        }
    });


    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

意图处理:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        // handles a click on a search suggestion; launches activity to show word
        Uri uri = intent.getData();
        Cursor cursor = managedQuery(uri, null, null, null, null);

        if (cursor == null) {
            finish();
        } else {
            cursor.moveToFirst();
            doMoreCode();
        }
    } else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // handles a search query
        String query = intent.getStringExtra(SearchManager.QUERY);
        //////////////////////////////////////////////////////
        //WANTED FEATURE!
        OpenSearchSuggestionsList();
        //WANTED FEATURE!
        //////////////////////////////////////////////////////



    }
}

清单:

    <activity
        android:name=".AddTeam"
        android:configChanges="keyboard|screenSize|orientation"
        android:label="@string/title_activity_teamchooser"
        android:launchMode="singleTop" >

        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
    </activity>

可搜索:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/title_activity_settings"
        android:hint="@string/search_hint"
        android:searchSettingsDescription="Enter Word"
        android:searchSuggestAuthority="com.mypackage.DataProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:searchSuggestIntentData="content://com.mypackage.DataProvider/teamdaten"
        android:searchSuggestSelection=" ?"
        android:searchSuggestThreshold="1"
        android:includeInGlobalSearch="true"
        >
 </searchable>

AddTeam 布局 xml 的一部分:

<android.support.v7.widget.SearchView
    android:id="@+id/searchView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:textColor="#000000"
    volleyballinfo:iconifiedByDefault="false"
    volleyballinfo:queryHint="@string/search_hint"/>

【问题讨论】:

    标签: android searchview android-search search-suggestion


    【解决方案1】:

    注意:我的回答仅基于源代码检查,可能不会产生正面/有利的结果。此外,下面的代码是从内存中编写的 - 它可能包含拼写错误。

    好的。在内部,SearchView 使用自定义 AutoCompleteTextView 来显示建议。此自定义 AutoCompleteTextView 通过多个渠道侦听 submit 事件:View.OnKeyListener,覆盖 SearchView#onKeyDown(int, KeyEvent)OnEditorActionListener

    submit 事件中(当按下 ENTER 键时 - 在您的情况下),使用 SearchView#dismissSuggestions 关闭建议弹出窗口:

    private void dismissSuggestions() {
        mSearchSrcTextView.dismissDropDown();
    }
    

    如您所见,SearchView#dismissSuggestions() 调用了AutoCompleteTextView#dismissDropDown()。因此,为了显示下拉菜单,我们应该可以调用 AutoCompleteTextView#showDropDown()

    但是,SearchView 使用的自定义 AutoCompleteTextView 实例是私有的,没有定义访问器。在这种情况下,我们可以尝试找到这个View,将其转换为AutoCompleteTextView,然后调用showDropDown()

    ....
    // Your snippet
    else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // handles a search query
        String query = intent.getStringExtra(SearchManager.QUERY);
        OpenSearchSuggestionsList(searchView);
    }
    ....
    
    // Edited
    // This method will accept the `SearchView` and traverse through 
    // all of its children. If an `AutoCompleteTextView` is found,
    // `showDropDown()` will be called on it.
    private void OpenSearchSuggestionsList(ViewGroup viewGroup) {
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);
    
            if (child instanceof ViewGroup) {
                OpenSearchSuggestionsList((ViewGroup)child);
            } else if (child instanceof AutoCompleteTextView) {
                // Found the right child - show dropdown
                ((AutoCompleteTextView)child).showDropDown();
                break; // We're done
            }
        }
    }
    

    期待您对此发表评论。

    【讨论】:

    • 我真的希望这会奏效,因为我喜欢你描述这种情况的方式。尽管如此,事实证明我的 searchView 只有一个孩子——让我大吃一惊的是一个 android.widget.LinearLayout!我不知道为什么会这样。
    • @Merlin1896 谢谢。在没有测试的情况下编写了代码:(。问题是,我们必须递归检查 SearchView 中的所有孩子。这意味着,如果我们找到一个 ViewGoup(能够持有 Views) - 在这种情况下,一个LinearLayout - 我们遍历它的个孩子。我会为你做一个编辑来测试。变化将发生在OpenSearchSuggestionsList()内部。
    • 太棒了!这样可行!你能解释一下为什么 LinearLayout 可以是 searchview 的 child 吗?还有一条迂腐评论:在OpenSearchSuggestionsList(child); 行中,您忘记将孩子放入 ViewGroup。
    • @Merlin1896 抱歉。固定。
    • @Merlin1896 Can you explain why a LinearLayout can be a child of a searchview? 你介意我稍后解释一下吗?我该上班了,:)。
    【解决方案2】:

    这会有所帮助,请注意使用 app appcompat 库中的 R 导入 android.support.v7.appcompat.R

    mQueryTextView = (AutoCompleteTextView) searchView.findViewById(R.id.search_src_text);
    
    mQueryTextView.showDropDown()
    

    【讨论】:

      【解决方案3】:

      接受的答案是一个很好的答案,并引导我找到另一个可能对其他人有益的简单答案:

      private void OpenSearchSuggestionsList() {
          int autoCompleteTextViewID = getResources().getIdentifier("search_src_text", "id", getPackageName());
          AutoCompleteTextView  searchAutoCompleteTextView = searchView.findViewById(autoCompleteTextViewID);
          searchAutoCompleteTextView.showDropDown();
      }
      

      【讨论】:

        【解决方案4】:

        在您的搜索视图中,有一个名为 onQueryTextSubmit 的覆盖方法,您可以先尝试从该方法返回 false。

        如果上面的方法不行,试试这个,

        @Override
          public boolean onQueryTextSubmit(String query) {
        
              InputMethodManager inputManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
              inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
              return false;
          }
        

        希望这会有所帮助:)

        【讨论】:

        • 对不起,这没有帮助 :( 建议列表仍然关闭
        • 我添加了一些代码 sn-ps,请参阅我的编辑。数据库结构高度基于“可搜索字典”示例:github.com/android/platform_development/blob/master/samples/…
        • 你能添加这个可搜索的视图吗?因为我找不到它。
        • 我添加了他们的布局 xml 部分。不知道你具体要求什么。这就是搜索视图的所有提及。搜索视图是 AddTeam 类的一部分。它不是内置在操作栏中,而是一个独立的字段。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-04
        • 2014-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多