Android 带有继承AppCompat主题的图标的动态微调器

Android 带有继承AppCompat主题的图标的动态微调器,android,material-design,android-spinner,android-appcompat,android-theme,Android,Material Design,Android Spinner,Android Appcompat,Android Theme,我正在努力实现两件事: 使我的微调器从AppCompat主题继承 尽可能在工具栏弹出菜单中向微调器元素添加图标 由于我无法实现第一点,我将重点关注这一点,但我还想在以后添加图标。现在,我的工具栏弹出菜单继承了AppCompat主题,但微调器没有,如下图所示。第一个图像显示工具栏中的(正确的)弹出菜单,而第二个图像显示微调器中的弹出菜单。这是未继承样式的微调器的示例。还是应该使用这种弹出式菜单样式 我已经尝试了很多东西,所以这个问题可能有多个重复,但我无法让它工作。下面的代码可能有什么错误?正

我正在努力实现两件事:

  • 使我的微调器从AppCompat主题继承
  • 尽可能在工具栏弹出菜单中向微调器元素添加图标
  • 由于我无法实现第一点,我将重点关注这一点,但我还想在以后添加图标。现在,我的工具栏弹出菜单继承了AppCompat主题,但微调器没有,如下图所示。第一个图像显示工具栏中的(正确的)弹出菜单,而第二个图像显示微调器中的弹出菜单。这是未继承样式的微调器的示例。还是应该使用这种弹出式菜单样式

    我已经尝试了很多东西,所以这个问题可能有多个重复,但我无法让它工作。下面的代码可能有什么错误?正确继承主题后,以后如何添加图标?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>
    
    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;
        }
    
    }
    
    MyAdapter adapter = new MyAdapter(getContext(), android.R.layout.simple_spinner_dropdown_item, mCategories);
    mSpinner.setAdapter(adapter);
    
    我曾尝试将各种样式直接添加到微调器中,但它不起作用

    在my AndroidManifest.xml中,我已将以下内容添加到应用程序标记中:

    android:theme="@style/MyTheme"
    
    通过改变主题和风格,我成功地做到了(或非常接近):

    只需添加到您的主题:

    <item name="android:spinnerDropDownItemStyle">@style/MySpinnerItem</item>
    
    这就是AppCompat主题

    最后,如果要向列表项添加图标,则必须创建自定义布局并以编程方式进行设置。您可以按照本教程进行解释。 基本上,你必须:

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

    我的问题的原因在线路上

    ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, mCategories);
    
    简单微调器\u下拉列表\u项目

    <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"/>
    
    <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"/>
    

    我们真的必须自己为纺纱机实现填充和所有功能吗?从表面上看,它似乎应该是开箱即用的。微调器的外观也是如此,而不仅仅是弹出菜单。例如,其他StackOverflow回答中也提出了这一点。事实上,它是开箱即用的,但由于某些原因,三星设备上的字体颜色不是AppCompat主题中的字体颜色,并且边距与所有设备的溢出菜单不同,这就是为什么我以我在回答中所描述的作为结束。我找不到任何继承该主题的设备。我试过两台三星设备和一台索尼设备以及多台模拟器。也许我必须和你一样做。看起来有点奇怪。
    <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"/>
    
    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;
        }
    
    }
    
    <?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>
    
    <?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);