带有继承AppCompat主题的图标的动态Spinner

时间:2016-02-02 17:17:13

标签: android material-design android-spinner android-appcompat android-theme

我正在努力实现两件事:

  1. 让我的Spinners继承AppCompat主题。
  2. 在工具栏弹出菜单中添加图标到微调器元素。
  3. 由于我无法实现我关注的第一点,但我也想稍后添加图标。就像现在一样,我的工具栏弹出菜单继承了AppCompat主题,但Spinners没有,如下图所示。第一个图像显示工具栏中的(正确)弹出菜单,而第二个图像显示Spinner的弹出菜单。这是一个不继承该样式的Spinner的示例。或者是否应该使用此弹出菜单样式?

    Toolbar inherits from AppCompat style Spinners do not inherit from AppCompat style

    我已经尝试过很多东西,所以这个问题可能有多个重复,但我无法让它发挥作用。下面的代码有什么问题?正确继承主题后,如何在以后添加图标?最低SDK版本为16,目标为23。

    的themes.xml:

    <resources>
    
        <style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
            <item name="windowActionBar">false</item>
            <item name="windowNoTitle">true</item>
    
            <item name="colorPrimary">@color/my_brown</item>
            <item name="colorPrimaryDark">@color/my_dark_gray</item>
            <item name="colorAccent">@color/my_green</item>
    
            <!-- This is just a test, it makes no difference. -->
            <item name="android:spinnerStyle">@style/MySpinnerStyle</item>
    
        </style>
    
        <style name="MyTheme" parent="MyTheme.Base"></style>
    
        <!--
            ActionBar style, applied directly to XML elements
        -->
        <style name="MyActionBarStyle" parent="@style/Widget.AppCompat.ActionBar">
            <item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
            <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:background">@color/my_brown</item>
            <item name="android:minHeight">?attr/actionBarSize</item>
        </style>
    
        <!--
            Spinner style, for testing. Also tried applied directly to xml Spinners.
        -->
        <style name="MySpinnerStyle" parent="@style/Widget.AppCompat.Spinner">
            <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
            <item name="android:popupMenuStyle">@style/Widget.AppCompat.Light.PopupMenu</item>
         </style>
    </resources>
    

    Spinner的设置简单如下:

    ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, mCategories);
    mSpinner.setAdapter(adapter);
    

    其中mSpinner是膨胀的Spinner,mCategories是String数组。在XML中,Spinner被定义为

    <Spinner
        android:id="@+id/my_spinner"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"/>
    

    我尝试直接向Spinner添加各种样式,但它不起作用。

    在我的AndroidManifest.xml中,我已将以下内容添加到Application标记中:

    android:theme="@style/MyTheme"
    

2 个答案:

答案 0 :(得分:1)

通过改变主题和风格,我设法做到了(或者非常接近它):

只需添加到您的主题:

<item name="android:spinnerDropDownItemStyle">@style/MySpinnerItem</item>

然后为MySpinnerItem创建一个继承自Widget.AppCompat.DropDownItem.Spinner

的样式
<style name="MySpinnerItem" parent="@style/Widget.AppCompat.DropDownItem.Spinner">
    <item name="android:textColor">@color/your_text_color</item>
    <item name="android:textSize">16sp</item>
    <item name="android:paddingLeft">16dp</item>
    <item name="android:paddingStart" tools:targetApi="jelly_bean_mr1">16dp</item>
    <item name="android:paddingRight">16dp</item>
    <item name="android:paddingEnd" tools:targetApi="jelly_bean_mr1">16dp</item>
</style>

这就是AppCompat主题。

最后,如果要向列表项添加图标,则必须创建自定义布局并以编程方式进行设置。您可以按照本教程http://android-er.blogspot.sg/2010/12/custom-arrayadapter-for-spinner-with.html解释它。 基本上你必须:

  • 创建自定义布局
  • 创建一个继承自ArrayAdapter
  • 的自定义适配器
  • 实施getCutomView()方法为每个项目设置不同的图片
  • 最后使用MyCustomAdapter.createFromResource(this, R.array.my_data, R.layout.my_cutom_item_layout);
  • 将适配器设置为微调器

答案 1 :(得分:0)

问题的原因在于

ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, mCategories);

这里我使用android.R.layout.simple_spinner_item,这可能是Spinner本身的意思。使用android.R.layout.simple_spinner_dropdown_item可以为下拉项目提供所需的外观。

this问题中详细介绍了这些内容之间的差异,但图片适用于较旧的Android版本。

供参考,以下是直接取自Android源代码的两种布局。

<强> simple_spinner_item

<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textAlignment="inherit"/>

<强> simple_spinner_dropdown_item

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="?android:attr/spinnerDropDownItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/dropdownListPreferredItemHeight"
    android:ellipsize="marquee"/>

在下拉列表中添加图标

现在,对于图标部分,我按照@euitam中的步骤进行操作,最后得到以下结果:

<强> MyAdapter:

public class MyAdapter extends ArrayAdapter<String>
{
    private String[] mCategories;
    private int[] mIcons;

    public CategoryDropDownAdapter(Context context, int layoutResourceId, String[] categories)
    {
        super(context, layoutResourceId, categories);
        mCategories = categories;

        // Add the same icon to all items, just for testing.
        mIcons = new int[mCategories.length];
        for (int i = 0; i < mIcons.length; i++)
        {
            mIcons[i] = R.drawable.my_icon;
        }
    }

    /**
    * View for a dropdown item.
    * */
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent)
    {
        View rowView = convertView;

        if (rowView == null)
        {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            rowView = inflater.inflate(R.layout.my_spinner_categories_dropdown_item, parent, false);
        }

        TextView categoryText = (TextView) rowView.findViewById(R.id.my_spinner_dropdown_item_text);
        categoryText.setText(mCategories[position]);

        ImageView icon = (ImageView) rowView.findViewById(R.id.my_spinner_dropdown_item_icon);
        icon.setImageResource(mIcons[position]);

        return rowView;
    }

    /**
     * The Spinner View that is selected and shown in the *Spinner*, i.e. not the dropdown item.
     * */
    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View spinnerView = convertView;

        if (spinnerView == null)
        {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            spinnerView = inflater.inflate(R.layout.my_spinner_categories_spinner_item, parent, false);
        }

        TextView categoryText = (TextView) spinnerView.findViewById(R.id.my_spinner_item_text);
        categoryText.setText(mCategories[position]);

        return spinnerView;
    }

}

<强> my_spinner_categories_dropdown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/my_spinner_dropdown_item_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <!-- Stolen from android.R.layout.simple_spinner_dropdown_item -->
    <TextView
        android:id="@+id/my_spinner_dropdown_item_text"
        style="?android:attr/spinnerDropDownItemStyle"
        android:singleLine="true"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:ellipsize="marquee" />

</LinearLayout>

<强> my_spinner_categories_spinner_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <!-- Stolen from android.R.layout.simple_spinner_dropdown_item -->
    <TextView
        android:id="@+id/my_spinner_item_text"
        style="?android:attr/spinnerDropDownItemStyle"
        android:singleLine="true"
        android:layout_width="0dp"
        android:layout_height="48dp"
        android:layout_weight="1"
        android:ellipsize="marquee" />

</LinearLayout>

最后,设置适配器:

MyAdapter adapter = new MyAdapter(getContext(), android.R.layout.simple_spinner_dropdown_item, mCategories);
mSpinner.setAdapter(adapter);