Honeycomb - 在操作栏内自定义SearchView

时间:2011-07-27 12:57:20

标签: android android-3.0-honeycomb

我有一个字段,用户可以在应用程序的操作栏中键入搜索查询。这在活动栏中使用菜单膨胀在操作栏中声明:

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
>
    <item
        android:id="@+id/action_search"
        android:showAsAction="ifRoom"
        android:actionViewClass="android.widget.SearchView"
        android:title="@string/search"
    ></item>
</menu>

我需要自定义SearchView的外观(例如背景和文本颜色)。到目前为止,我找不到使用XML(使用样式或主题)的方法。

在给菜单充气时,我唯一的选择是在代码中执行此操作吗?


编辑#1:我尝试过编程,但我无法通过简单的方法设置文本颜色。另外,当我执行searchView.setBackgroundResource(...)时,背景设置在全局小部件上(当SearchView被图标化时)。

编辑#2:关于Search Developer Reference的信息不多

6 个答案:

答案 0 :(得分:9)

如果你想改变图标,Seibelj有一个很好的答案。但你需要 为每个API版本执行此操作。我正在使用带有ActionBarSherlock的ICS,这对我来说并不合适,但确实让我朝着正确的方向前进。

下面我更改文字颜色和提示颜色。我展示了如何改变它 图标也是,虽然我现在对此没兴趣(你可能想要使用默认图标来保持一致)

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    // Set up the search menu
    SearchView searchView = (SearchView)menu.findItem(R.id.action_search).getActionView();
    traverseView(searchView, 0);

    return true;
}

private void traverseView(View view, int index) {
    if (view instanceof SearchView) {
        SearchView v = (SearchView) view;
        for(int i = 0; i < v.getChildCount(); i++) {
            traverseView(v.getChildAt(i), i);
        }
    } else if (view instanceof LinearLayout) {
        LinearLayout ll = (LinearLayout) view;
        for(int i = 0; i < ll.getChildCount(); i++) {
            traverseView(ll.getChildAt(i), i);
        }
    } else if (view instanceof EditText) {
        ((EditText) view).setTextColor(Color.WHITE);
        ((EditText) view).setHintTextColor(R.color.blue_trans);
    } else if (view instanceof TextView) {
        ((TextView) view).setTextColor(Color.WHITE);
    } else if (view instanceof ImageView) {
        // TODO dissect images and replace with custom images
    } else {
        Log.v("View Scout", "Undefined view type here...");
    }
}

答案 1 :(得分:5)

添加我对不同Android版本可能更高效和安全的东西。

您实际上可以从字符串ID名称中获取数字ID值。使用android的hierarchyviewer工具,您实际上可以找到您感兴趣的内容的字符串ID,然后使用findViewById(...)查找它们。

下面的代码设置编辑字段本身的提示和文本颜色。你可以为你希望设计风格的其他方面应用相同的模式。

private static synchronized int getSearchSrcTextId(View view) {
    if (searchSrcTextId == -1) {
        searchSrcTextId = getId(view, "android:id/search_src_text");
    }
    return searchSrcTextId;
}

private static int getId(View view, String name) {
    return view.getContext().getResources().getIdentifier(name, null, null);
}

@TargetApi(11)
private void style(View view) {
    ImageView iv;

    AutoCompleteTextView actv = (AutoCompleteTextView) view.findViewById(getSearchSrcTextId(view));
    if (actv != null) {
        actv.setHint(getDecoratedHint(actv,
            searchView.getContext().getResources().getString(R.string.titleApplicationSearchHint),
            R.drawable.ic_ab_search));
        actv.setTextColor(view.getContext().getResources().getColor(R.color.ab_text));
        actv.setHintTextColor(view.getContext().getResources().getColor(R.color.hint_text));
    }
}

答案 2 :(得分:3)

您可以使用属性android:actionLayout代替您可以指定要充气的布局。只需拥有SearchView的布局,您就不必真正修改任何内容。

关于更改SearchView上可能无法实现的文字样式,因为SearchViewViewGroup。您可能应该尝试通过主题更改文本颜色。

答案 3 :(得分:2)

如果有人想直接修改视图,您可以通过以下方式更改颜色/字体/图像并自定义搜索框。它包含在try / catch中,以防版本或发行版之间存在差异,因此如果失败,它不会使应用程序崩溃。

        // SearchView structure as we currently understand it:
        // 0 => linearlayout
        //      0 => textview (not sure what this does)
        //      1 => image view (the search icon before it's pressed)
        //      2 => linearlayout
        //           0 => linearlayout
        //               0 => ImageView (Search icon on the left of the search box)
        //               1 => SearchView$SearchAutoComplete (Object that controls the text, subclass of TextView)
        //               2 => ImageView (Cancel icon to the right of the text entry)
        //           1 => linearlayout
        //               0 => ImageView ('Go' icon to the right of cancel)
        //               1 => ImageView (not sure what this does)
        try {
            LinearLayout ll = (LinearLayout) searchView.getChildAt(0);
            LinearLayout ll2 = (LinearLayout) ll.getChildAt(2);
            LinearLayout ll3 = (LinearLayout) ll2.getChildAt(0);
            LinearLayout ll4 = (LinearLayout) ll2.getChildAt(1);
            TextView search_text = (TextView) ll3.getChildAt(1);
            search_text.setTextColor(R.color.search_text);
            ImageView cancel_icon = (ImageView)ll3.getChildAt(2);
            ImageView accept_icon = (ImageView)ll4.getChildAt(0);
            cancel_icon.setBackgroundDrawable(d);
            accept_icon.setBackgroundDrawable(d);
        } catch (Throwable e) {
            Log.e("SearchBoxConstructor", "Unable to set the custom look of the search box");
        }

此示例显示更改取消/接受图像的文本颜色和背景颜色。 searchView是一个已经使用它的背景颜色实例化的SearchView对象:

Drawable d = getResources().getDrawable(R.drawable.search_widget_background);
searchView.setBackgroundDrawable(d);

这是可绘制的代码:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="@color/white" />

</shape>

显然,这很麻烦,但现在还可以。

答案 4 :(得分:1)

从ICS可以使用主题和样式。我正在使用ActionBarSherlock,它也适用于HC及以下。

  1. 添加样式以定义“android:textColorHint”:

    <style name="Theme.MyHolo.widget" parent="@style/Theme.Holo">
        <item name="android:textColorHint">@color/text_hint_corp_dark</item>
    </style>
    
  2. 将此作为“actionBarWidgetTheme”应用于您的主题:

    <style name="Theme.MyApp" parent="@style/Theme.Holo.Light.DarkActionBar">
        ...
        <item name="android:actionBarWidgetTheme">@style/Theme.MyHolo.widget</item>
    </style>
    
  3. 的Presto!如果启动了任何可能有其他主题生效的小部件,请确保使用getSupportActionBar().getThemedContext()(或getSupportActionBar()用于ActionBarSherlock)。

答案 5 :(得分:0)

如何在Activity中扩展菜单xml?如果您通过在Activity中使用getMenuInflator()来扩展菜单,则菜单和searchView将获得附加到活动的主题上下文。

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

如果在API-15上检查Activity.getMenuInflator()的源代码,则可以看到主题上下文代码。在这里。

     */
public MenuInflater getMenuInflater() {
    // Make sure that action views can get an appropriate theme.
    if (mMenuInflater == null) {
        initActionBar();
        if (mActionBar != null) {
            mMenuInflater = new MenuInflater(mActionBar.getThemedContext());
        } else {
            mMenuInflater = new MenuInflater(this);
        }
    }
    return mMenuInflater;
}