【问题标题】:Set search hint dynamically动态设置搜索提示
【发布时间】:2010-10-25 04:14:14
【问题描述】:

有人知道如何动态设置 android 搜索对话框提示吗? T 尝试做类似的事情:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
 android:label="@string/search_label"
 android:hint="@string/search_hint"
 android:id="@+id/search_dialog_text">
</searchable>

某处:

@Override
public boolean onSearchRequested() {
  Bundle appSearchData = new Bundle();
  appSearchData.putString("SomeSpecificParam", SomeClass.class.getName());
  startSearch("", false, appSearchData, false);
  EditText  text = (EditText )findViewById(R.id.search_dialog_text);
  text.setHint("Search something else");
  return true;
}

但 text 等于 null。

所以期待您的建议。谢谢。

【问题讨论】:

    标签: android android-searchmanager


    【解决方案1】:

    这感觉很老套,但对我有用——不是真正的动态,但可以在我需要的两个搜索提示之间交替使用:

    1. 我创建了第二个 searchable.xml(如 Android search docs 中所述),名为 searchable2.xml,并定义了我的第二个搜索提示。
    2. 我创建了一个从原始活动扩展而来的虚拟活动,并且没有覆盖任何内容。
    3. 在清单中,虚拟活动与新的 searchable2.xml 相关联:

      <activity android:name=".MainActivity">
          <intent-filter>
              <action android:name="android.intent.action.VIEW" />
              <action android:name="android.intent.action.SEARCH" />
          </intent-filter>
          <meta-data android:name="android.app.searchable"
              android:resource="@xml/searchable"/>
      </activity>
      
      <activity android:name=".DummyActivity">
          <intent-filter>
              <action android:name="android.intent.action.VIEW" />
              <action android:name="android.intent.action.SEARCH" />
          </intent-filter>
          <meta-data android:name="android.app.searchable"
              android:resource="@xml/searchable2"/>
      </activity>
      
    4. 在“MainActivity”中,我覆盖了“onSearchRequested()”以引用适当的可搜索活动:

      
      public boolean onSearchRequested()
       {
             SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
      if(searchManager!=null) { // start the search with the appropriate searchable activity // so we get the correct search hint in the search dialog if(/* your condition here */) searchManager.startSearch(null, false,new ComponentName(this, MainActivity.class), null, false); else searchManager.startSearch(null, false,new ComponentName(this, DummyActivity.class), null, false); return true; } return false; }

    恶心。但绝望的时候需要绝望的措施......

    AFAIK,从查看 Android 源代码来看,该类仅用于查找元数据,但如果有人知道不同,请告诉我。

    【讨论】:

    • 非常有趣的 hack。乱七八糟,但似乎很有效。你能想出一种方法让这种情况动态发生吗?即在运行时更新搜索提示?例如使用正在搜索的项目数的实时计数格式化提示字符串
    【解决方案2】:

    他们在http://developer.android.com/guide/topics/search/search-dialog.html#SearchableConfiguration 添加了一条说明

    注意:系统使用这个文件来实例化一个 SearchableInfo 对象,但是你不能在运行时自己创建这个对象——你必须在 XML 中声明可搜索的配置。

    所以看来你的问题的答案是你不能动态设置搜索对话框提示。

    【讨论】:

      【解决方案3】:

      我设法通过 ABS 使用 OnActionExpandListener 和自定义 actionView 来做到这一点,例如:

      menu.add("Search")
      .setActionView(R.layout.collapsible_edittext)
      .setOnActionExpandListener(new MenuItem.OnActionExpandListener()
      {
          @Override
          public boolean onMenuItemActionExpand(MenuItem item) {
              ((EditText) item.getActionView()).setHint("Your custom text here");
              return true;
          }
      
          @Override
          public boolean onMenuItemActionCollapse(MenuItem item) {
              return true;
          }
      });
      

      使用 collapsible_edittext.xml:

      <EditText
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textColor="@color/search_fg"
          android:background="@drawable/textfield_default_holo_light"
          android:hint="[will be replaced at runtime]"/>
      

      【讨论】:

        【解决方案4】:

        如果您使用ToolbarSearchView 小部件,您可以通过调用轻松设置搜索查询提示:

        SearchView.setQueryHint(CharSequence hint)
        

        【讨论】:

          【解决方案5】:

          看来你快到了。

          SearchDialog 源这样做是为了让自动完成可编辑。

          mSearchAutoComplete = (SearchAutoComplete) findViewById(com.android.internal.R.id.search_src_text);
          

          (注意SearchAutoComplete 类是AutoCompleteTextView 的子类)

          【讨论】:

            【解决方案6】:

            有一个比上述任何一个都简单得​​多的答案。它为您的活动加载默认的 searchable.xml,然后使用 java 反射更新 SearchableInfo 实例中的私有 mHintId 字段:

            @Override
            public void onPrepareOptionsMenu(Menu menu) {
                SearchManager searchManager = (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE);
                SearchableInfo si = searchManager.getSearchableInfo( getActivity().getComponentName() );
            
                try {
                    Field mHintId = si.getClass().getDeclaredField("mHintId");
                    mHintId.setAccessible(true);
                    mHintId.setInt(si, R.string.your_custom_hint);
                } catch (Exception e) {
                }
            
                MenuItem mi = menu.findItem(R.id.menu_search);
                SearchView searchView = (SearchView)mi.getActionView();
                searchView.setSearchableInfo( si );
            }
            

            【讨论】:

            • 以上是最好、最简单的方法。忘记所有其他复杂的建议!
            • @zyamys 您从哪个类和什么方法调用 invalidateLayout() 以便调用此 onPrepareOptionsMenu() 覆盖?谢谢!
            • 由框架调用,不需要调用Activity。 invalidateOptionsMenu() 除非您出于某些不相关的原因需要。
            【解决方案7】:

            感谢 Murakami 先生的想法,我已经实现了相同的概念来执行切换搜索,并且在我看来,这不是 hack,而是它的 OOP 之美。下面的程序在操作栏中有一个切换图标,用于在搜索提示之间切换。

            1. RestaurantListingActivity.java

              public class RestaurantListingActivity extends BaseMainActivity implements
              TabListener {
              private boolean isRestaurantSearch = true;
              private SearchManager searchManager;
              private SearchView searchView;
              
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  ActionBar aBar = getActionBar();
                  aBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
                  aBar.addTab(aBar.newTab().setText("Place Order").setTabListener(this));
                  aBar.addTab(aBar.newTab().setText("My Account").setTabListener(this));
                  aBar.addTab(aBar.newTab().setText("Favorite").setTabListener(this));
                  aBar.addTab(aBar.newTab().setText("Vendor Portal").setTabListener(this));
              }
              
              @Override
              public boolean onCreateOptionsMenu(Menu menu) {
                  getMenuInflater().inflate(R.menu.restaturant_listing_menu, menu);
                  searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
                  searchView = (SearchView) menu.findItem(R.id.rlm_search)
                          .getActionView();
                  searchView.setSearchableInfo(searchManager
                          .getSearchableInfo(new ComponentName(this,
                                  RestaurantListingActivity.class)));
                  return super.onCreateOptionsMenu(menu);
              }
              @Override
              public boolean onOptionsItemSelected(MenuItem item) {
                  switch (item.getItemId()) {
                  case R.id.rlm_toggle:
              isRestaurantSearch = !isRestaurantSearch;
                  if (isRestaurantSearch)
                      searchView.setSearchableInfo(searchManager
                              .getSearchableInfo(new ComponentName(this,
                                      RestaurantListingActivity.class)));
                  else
                      searchView.setSearchableInfo(searchManager
                              .getSearchableInfo(new ComponentName(this,
                                      RestaurantFoodSwitcherActivity.class)));
              
              
                  break;
              case R.id.rlm_change_loc:
              
                  break;
              case R.id.rlm_filter_search:
              
                  break;
              }
              
                  return super.onOptionsItemSelected(item);
              }
              
              @Override
              public void onTabReselected(Tab tab, FragmentTransaction ft) {
                  // TODO Auto-generated method stub
              
              }
              
              @Override
              public void onTabSelected(Tab tab, FragmentTransaction ft) {
              // TODO Auto-generated method stub
              }
              
              @Override
              public void onTabUnselected(Tab tab, FragmentTransaction ft) {
                  // TODO Auto-generated method stub
              
              }
              
              @Override
              public void setScreenData(Object screenData, int event, long time) {
                  // TODO Auto-generated method stub
              
              }
              
              @Override
              public Activity getMyActivityReference() {
                  // TODO Auto-generated method stub
                  return null;
              }
              
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
              
              }
              }
              
            2. restaurant_listing_menu

            <item
                android:id="@+id/rlm_toggle"
                android:showAsAction="always"
                android:title="Toggle Search"
                android:icon="@drawable/ic_action_refresh"
                >
            </item>
            <item
                android:id="@+id/rlm_search"
                android:showAsAction="always|collapseActionView"
                android:title="Search"
                android:icon="@drawable/ic_action_search"
                android:actionViewClass="android.widget.SearchView"
                >
            </item>
            <item
                android:id="@+id/rlm_filter_search"
                android:showAsAction="ifRoom"
                android:title="Filter Search"
                android:icon="@drawable/ic_action_settings"
                >
            </item>
            <item
                android:id="@+id/rlm_change_loc"
                android:showAsAction="ifRoom"
                android:title="Change Location"
                android:icon="@drawable/ic_action_location_off"
                >
            </item>
            

            1. res>xml中的searchablerestra.xml

              <?xml version="1.0" encoding="utf-8"?>
              <searchable xmlns:android="http://schemas.android.com/apk/res/android"
              android:hint="@string/search_hint_restra"
              android:label="@string/app_name">
              </searchable>
              
            2. RestaurantFoodSwitcherActivity.java

              public class RestaurantFoodSwitcherActivity extends RestaurantListingActivity {
              }
              
            3. searchablefood.xml

              <?xml version="1.0" encoding="utf-8"?>
              <searchable xmlns:android="http://schemas.android.com/apk/res/android"
                  android:hint="@string/search_hint_food"
                  android:label="@string/app_name">
              </searchable>
              
            4. manifest.xml

              <activity         android:name="com.example.app.ui.activity.RestaurantListingActivity" >
                  <!-- This intent-filter identifies this activity as "searchable" -->
                  <intent-filter>
                      <action android:name="android.intent.action.SEARCH" />
              
                      <category android:name="android.intent.category.DEFAULT" />
                  </intent-filter>
                  <!-- This metadata entry provides further configuration details for searches -->
                  <!-- that are handled by this activity. -->
                  <meta-data
                      android:name="android.app.searchable"
                      android:resource="@xml/searchablerestra"
              
                       />
              </activity>
              <activity android:name="com.example.app.ui.activity.RestaurantFoodSwitcherActivity">
                  <!-- This intent-filter identifies this activity as "searchable" -->
                  <intent-filter>
                      <action android:name="android.intent.action.SEARCH" />
              
                      <category android:name="android.intent.category.DEFAULT" />
                  </intent-filter>
                  <!-- This metadata entry provides further configuration details for searches -->
                  <!-- that are handled by this activity. -->
                   <meta-data
                      android:name="android.app.searchable"
                      android:resource="@xml/searchablefood"
                       />
              </activity>
              

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-07-26
              • 2021-05-08
              • 1970-01-01
              • 2010-09-13
              • 1970-01-01
              • 1970-01-01
              • 2019-05-21
              相关资源
              最近更新 更多