【问题标题】:How can I fix the Spinner style for Android 4.x placed on top of the Toolbar如何修复放置在工具栏顶部的 Android 4.x 微调器样式
【发布时间】:2014-11-05 11:16:49
【问题描述】:

根据Android documentation,Spinner 小部件支持 Material Design 样式。

所以我决定在我的应用中使用它,将它放在工具栏的顶部。

layout/activity_base.xml

<android.support.v7.widget.Toolbar
    android:id="@+id/my_awesome_toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="5dp"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
    <Spinner
        android:id="@+id/spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
 </android.support.v7.widget.Toolbar>

活动主题

<style name="BaseAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/omni_primary_color</item>
    <item name="colorPrimaryDark">@color/omni_primary_color_dark</item>
    <item name="colorAccent">@color/omni_accent_color</item>
</style>

BaseActivity.java

public class BaseActivity extends ActionBarActivity {

    @InjectView(R.id.my_awesome_toolbar)
    Toolbar mToolbar;

    @InjectView(R.id.spinner)
    Spinner spinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base);
        ButterKnife.inject(this);
        //setup toolbar
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        mToolbar.setNavigationIcon(R.drawable.ic_action_navigation_menu);
          
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mToolbar.getContext(),
                R.array.planets_array, R.layout.support_simple_spinner_dropdown_item);
        adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
    }
}

在 Lollipop 微调器和下拉菜单上看起来不错,尽管下拉菜单的背景颜色是黑色,而菜单下拉菜单是白色的。我猜app:popupTheme="@style/ThemeOverlay.AppCompat.Light" 不会传播到微调器。

Android 5.0

现在最大的问题是在 Android 4.x 中,下拉背景颜色为白色(popupTheme 已传播?),而微调器旁边的图标为黑色。

Android 4.4

如何在 XML 中正确设置它或在代码中实现它以使其在 Android 5 和 4 上都可以工作?理想情况下,我希望两者看起来都像在 Android 5 上,但带有白色微调器下拉菜单(如设置菜单下拉菜单)。

更新

我注意到设置属性colorControlNormal 会影响微调器的过滤器图标。如果有人发现如何将其用于 Spinner(无需更改其他内容控件),那么我的解决方案将把该发现与 @Sven 答案结合起来。

更新

以下更改修复了微调器文本和弹出颜色的问题。所以最终解决方案的唯一问题是过滤器图标。

ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getSupportActionBar().getThemedContext(),
                R.array.planets_array, R.layout.support_simple_spinner_dropdown_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

更新

我发现过滤器图标实际上是为微调器指定的android:background 的一部分,并且它是透明的。提供自己的背景可以解决它,例如

<item name="android:background">?android:selectableItemBackground</item>

谜团解开!

最后一块拼图是 Android 5 上的弹出窗口,它有黑色背景和白色文本,但我想它可以通过自定义布局来解决。如果没有人提供完整的答案,我会自己做并标记为已接受。

【问题讨论】:

  • 尝试使用getSupportActionBar().getThemedContext() 而不是mToolbar.getContext()
  • @Selvin 我已经尝试过了。看起来一模一样
  • @Loop 我也遇到了同样的问题,你找到解决办法了吗?
  • 对于微调器图标,this 可能会有所帮助。
  • @Loop 我在同样的事情上苦苦挣扎,发现将 AppCompat 从 21.0.0 更新到 21.0.2 修复了微调器的过滤器图标颜色。我通过使用自定义布局解决了其他问题。

标签: android android-layout android-spinner android-toolbar


【解决方案1】:

我知道这已经晚了,但是当我自己遇到这个问题时,我遇到了这个问题,我在Google I/O 2014 appBrowseSessionsActivity 中找到了解决方案并对其进行了调整。

布局

toolbar_spinner.xml

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

    <Spinner
        android:id="@+id/toolbar_spinner"
        style="@style/Widget.MyApp.HeaderBar.Spinner"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"/>

</LinearLayout>

toolbar_spinner_item_actionbar.xml

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

    <TextView
        android:id="@android:id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawablePadding="8dp"
        android:drawableRight="@drawable/spinner_triangle"
        android:fontFamily="sans-serif"
        android:paddingLeft="16dp"
        android:paddingRight="4dp"
        android:textColor="#ffffffff"
        android:textSize="18dp"
        android:textStyle="bold"/>

</LinearLayout>

spinner_triangledrawable 可以在here 找到。

toolbar_spinner_item_dropdown.xml

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

    <TextView
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:drawablePadding="8dp"
        android:gravity="center_vertical|start"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="#ff333333"
        android:textSize="16sp"/>
        
</LinearLayout>

样式

toolbar_spinner.xml 使用以下样式。

<style name="Widget.MyApp.HeaderBar.Spinner" parent="Widget.AppCompat.Light.Spinner.DropDown.ActionBar">
        <item name="android:background">?android:selectableItemBackground</item>
        <item name="android:dropDownSelector">?android:selectableItemBackground</item>
        <item name="android:divider">@null</item>
        <item name="android:overlapAnchor">true</item>
</style>

适配器

需要更改此适配器以满足您自己的需要。 getTitle() 返回微调器中显示的每个项目的文本。

private class YourObjectSpinnerAdapter extends BaseAdapter {
    private List<YourObject> mItems = new ArrayList<>();

    public void clear() {
        mItems.clear();
    }

    public void addItem(YourObject yourObject) {
        mItems.add(yourObject);
    }

    public void addItems(List<YourObject> yourObjectList) {
        mItems.addAll(yourObjectList);
    }

    @Override
    public int getCount() {
        return mItems.size();
    }

    @Override
    public Object getItem(int position) {
        return mItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getDropDownView(int position, View view, ViewGroup parent) {
        if (view == null || !view.getTag().toString().equals("DROPDOWN")) {
            view = getLayoutInflater().inflate(R.layout.toolbar_spinner_item_dropdown, parent, false);
            view.setTag("DROPDOWN");
        }

        TextView textView = (TextView) view.findViewById(android.R.id.text1);
        textView.setText(getTitle(position));

        return view;
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {
        if (view == null || !view.getTag().toString().equals("NON_DROPDOWN")) {
            view = getLayoutInflater().inflate(R.layout.
                    toolbar_spinner_item_actionbar, parent, false);
            view.setTag("NON_DROPDOWN");
        }
        TextView textView = (TextView) view.findViewById(android.R.id.text1);
        textView.setText(getTitle(position));
        return view;
    }

    private String getTitle(int position) {
        return position >= 0 && position < mItems.size() ? mItems.get(position).title : "";
    }
}

将微调器添加到您的工具栏

Toolbar toolbar = getActionBarToolbar();

View spinnerContainer = LayoutInflater.from(this).inflate(R.layout.toolbar_spinner,
        toolbar, false);
ActionBar.LayoutParams lp = new ActionBar.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
toolbar.addView(spinnerContainer, lp);

YourObjectSpinnerAdapter spinnerAdapter = new YourObjectSpinnerAdapter();
spinnerAdapter.addItems(getMyObjectSpinnerData());

Spinner spinner = (Spinner) spinnerContainer.findViewById(R.id.toolbar_spinner);
spinner.setAdapter(spinnerAdapter);

结果

【讨论】:

  • 现在还不晚:)。我想补充一点,toolbar_spinner.xml 不是必需的。你可以把 放在 里面。这样你就不需要容器充气和额外的可绘制的三角形。 Spinner 将使用默认的可绘制对象。
  • getLayoutInflater() 好像识别不出来,BaseAdapter中的LayoutIinflater怎么弄?
  • 我认为这在 Gingerbread 上失败了:... 原因:android.content.res.Resources$NotFoundException: Resource is not a Drawable (color or path): TypedValue{t=0x2/d =0x101030e a=2} 和 0x101030e 似乎是 developer.android.com/reference/android/… - 在 styles.xml 中删除 ?android:selectableItemBackground 的使用会产生一些 UI 问题。
  • 这在棒棒糖上效果不佳。那里的背景很暗:/
  • @Xylian:将android:theme="@style/ThemeOverlay.AppCompat.Light" 添加到您的微调器组件中,为我修复了它。我已经编辑了反映我最后两个 cmets 的答案。
【解决方案2】:

不要在 Xml 中实现 Spinner

final ArrayAdapter spinnerAdapter = ArrayAdapter.createFromResource(getSupportActionBar().getThemedContext(),
            R.array.main_navigation_list, R.layout.spinner_text);
    spinnerAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
    mNavigationTags = getResources().getStringArray(R.array.main_navigation_list);


    mNavigationSpinner = new Spinner(getSupportActionBar().getThemedContext());
    mNavigationSpinner.setAdapter(spinnerAdapter);

    mNavigationSpinner.setOnItemSelectedListener(this);
    mToolbar.addView(mNavigationSpinner);

这样微调器旁边的图标就会变成白色

【讨论】:

  • 这是要走的路!
【解决方案3】:

对不起,我的英语很差。 :) 我觉得还是直接在Toolbar中创建spinner比较好。

这是我的片段中的一个示例。

public class Testfragment1 extends Fragment {

    Toolbar mToolbar;
    Spinner mSpinner;
    .....

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        .......                  
        mToolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
        //you can also set the style with the constructor
        mSpinner = new Spinner(getActivity());
        String[] frags = new String[]{
                "category1",
                "category2",
                "category3",
        };
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,frags);
        mSpinner.setAdapter(arrayAdapter);
        mToolbar.addView(mSpinner);
        return inflater.inflate(R.layout.fragment_testfragment1, container, false);
    }

    .........

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mToolbar != null && mSpinner != null) {
            mToolbar.removeView(mSpinner);
        }
    }
}

在我的 android-4.1-device 上看起来不错: android-4.1-spinner

【讨论】:

  • 感谢您的回答,我会试一试。但是,我认为使用内部小部件实现不是一个好主意,因为它可能会在 appcompat 中更改,恕不另行通知。此外,在完整的解决方案中,我希望微调弹出窗口看起来像 Settins 中的弹出窗口(白色背景和白色文本)
  • 你是如何在 Android 4.1 上编译的?使用 ToolBar 时,它会强制我将 minSDK 设置为 21,因此不会在更低的版本上编译
  • TintSpinner 是一个内部小部件,并且会发生变化。这个想法是将内部小部件作为公共小部件发布,因此 API 将受到一些修改(例如,TintSpinner 将被简称为 Spinner)。请不惜一切代价避免使用此方法,除非您打算坚持使用当前的 AppCompat 库版本及其所有错误。
  • 这些类在 appcompat v22.2 中不存在
  • @LOG_TAG 它是为抽屉式导航设计的,当您将其更改为另一个片段时,您将看不到微调器。
【解决方案4】:

我正在努力解决完全相同的问题。

尝试更改下拉视图资源。至少,这为我解决了文本颜色问题 - 但是箭头图标颜色仍然很暗。所以这只是部分解决方法。

setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

【讨论】:

  • 我已经尝试了一半,成功了。无论如何,我正在寻找完整的解决方案。其实我有个想法可以试试。如果可行,我会在这里发布。
  • 我发现设置 'colorControlNormal' 会将过滤器图标更改为该颜色。但是,它也会更改应用程序内容中的其他控件。所以现在的挑战是将该属性应用于工具栏上的微调器。将该属性应用于工具栏样式什么都不做。
【解决方案5】:

一种不完美的简单方法,但对于 4.x 和 5.0 来说足够统一

我从布局文件中删除了&lt;Spinner&gt;,并以编程方式添加了它——这使得白色三角形能够正确显示。

我还使用 appcompat 所需的颜色创建了一个下拉项布局。

layout/spinner_dropdown_item.xml,注意android:background="@color/primaryColor"

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@android:id/text1"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceListItemSmall"
      android:gravity="center_vertical"
      android:paddingLeft="12dp"
      android:paddingRight="12dp"
      android:background="@color/primaryColor"
      android:minHeight="?android:attr/listPreferredItemHeightSmall" />

在活动中:

    SpinnerAdapter spinnerAdapter = ArrayAdapter.createFromResource(getApplicationContext(), R.array.your_array, R.layout.spinner_dropdown_item);
    Spinner navigationSpinner = new Spinner(getSupportActionBar().getThemedContext());
    navigationSpinner.setAdapter(spinnerAdapter);
    toolbar.addView(navigationSpinner, 0);

它并不完美,当您单击它们时项目不会突出显示,但在我们等待未来的 appcompat 库解决这些问题时已经足够了(无论如何希望如此)。

【讨论】:

    【解决方案6】:

    我花了两天时间解决这个问题,但现在在阅读了很多答案后,我可以发布我的解决方案。我已经为微调器项目和弹出窗口实现了两个自定义布局。为微调器设置此属性:android:background="?android:selectableItemBackground" 默认微调器黑色箭头是隐藏的,我们可以使用我们喜欢的。我使用 setDropDownVerticalOffset(int) 方法来管理 Lollipop Android 版本上的弹出位置。

    我的应用全局主题是

    <style name="AppTheme" parent="AppTheme.Base">
    
    </style>
    
    <style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/primary</item>
        <item name="colorPrimaryDark">@color/primary_dark</item>
        <item name="colorAccent">@color/accent</item>
        <item name="android:windowBackground">@color/window_background</item>
    </style>
    

    现在,包含工具栏和微调器的活动布局:

    activity_main.xml

    <RelativeLayout
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
    
        android:clickable="true" >
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            android:elevation="4dp"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" >
    
                <Spinner 
                    android:id="@+id/spinner_rss"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:theme="@style/ThemeOverlay.AppCompat.Light"
                    android:background="?android:selectableItemBackground" />
    
             </android.support.v7.widget.Toolbar>
    </RelativeLayout>
    

    custom_spinner_toolbar.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
    <TextView
        android:id="@+id/spinner_item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:singleLine="true"
        android:textColor="@android:color/white"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
         />
    
    <ImageView
        android:contentDescription="@string/content_description_arrow_dropdown"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/spinner_item_text"
        android:layout_toEndOf="@+id/spinner_item_text"
        android:paddingTop="6dp"
        android:src="@drawable/ic_arrow_drop_down_white_24dp" />
    
    </RelativeLayout>
    

    custom_spinner_dropdown_item.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
    
        <CheckedTextView
            android:id="@+id/spinner_item_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:singleLine="true"
            android:textColor="@android:color/black"
            android:textSize="16sp" />
    
    </LinearLayout>
    

    SpinnerAdapter.java

    public class SpinnerAdapter extends BaseAdapter
    {
       private Context mContext;
       private List<String> mValuesList;
    
       public SpinnerAdapter(Context mContext, List<String> mValuesList)
       {
           this.mContext = mContext;
           this.mValuesList = mValuesList;
       }
    
       @Override
       public int getCount() 
       {
           return mValuesList.size();
       }
    
       @Override
       public Object getItem(int position) 
       {
           return mValuesList.get(position);
       }
    
       @Override
       public long getItemId(int position) {
           // TODO Auto-generated method stub
           return 0;
       }
    
       @Override
       public View getDropDownView(int position, View view, ViewGroup parent) 
       {
          if (view == null || !view.getTag().toString().equals("DROPDOWN")) 
          {
             LayoutInflater inflater = LayoutInflater.from(mContext);
             view = inflater.inflate(R.layout.custom_spinner_dropdown_item, parent, false);
             view.setTag("DROPDOWN");
          }
    
          TextView textView = (TextView) view.findViewById(R.id.spinner_item_text);
          textView.setText(getTitle(position));
    
          return view;
      }
    
      @Override
      public View getView(int position, View view, ViewGroup parent) 
      { 
          if (view == null || !view.getTag().toString().equals("NON_DROPDOWN")) 
          {
             LayoutInflater inflater = LayoutInflater.from(mContext);
             view = inflater.inflate(R.layout.custom_spinner_toolbar, parent, false);
             view.setTag("NON_DROPDOWN");
          }
    
          TextView textView = (TextView) view.findViewById(R.id.spinner_item_text);
          textView.setText(getTitle(position));
          return view;
       }
    
       private String getTitle(int position) 
       {
          return position >= 0 && position < mValuesList.size() ?   mValuesList.get(position) : "";
       }
    }
    

    最后是activity源码的相关部分:

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
    
        final ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        actionBar.setDisplayHomeAsUpEnabled(true);
    
        mSpinner = (Spinner) findViewById(R.id.spinner_rss);
    
        String[] items = getResources().getStringArray(R.array.spinner_rss_items);
        List<String> spinnerItems = new ArrayList<String>();
    
        for(int i = 0; i < items.length; i++)
        {
            spinnerItems.add(items[i]);
        }
    
        SpinnerAdapter adapter = new SpinnerAdapter(actionBar.getThemedContext(), spinnerItems);
        mSpinner.setAdapter(adapter);
    
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
        {
            mSpinner.setDropDownVerticalOffset(-116);
        }
    }
    

    这些是 Lollipop 和 Kitkat 的结果:

    希望对您有所帮助! :)

    【讨论】:

      【解决方案7】:

      你不能这样做吗?

      微调器项目的自定义 xml 文件:your_spinner.xml:

      <?xml version="1.0" encoding="utf-8"?>
      <TextView  
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent" 
          android:layout_height="wrap_content" 
          android:textColor="#000"         
          android:background="#FFF"
          />
      

      使用它来显示微调器项目:

      ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.your_spinner,list);
      

      然后删除下拉资源。

      【讨论】:

      • 它没有像我预期的那样工作。它只是改变了文本部分,看起来非常糟糕。外观可以调整,但过滤器图标保持不变。
      【解决方案8】:

      与微调器的问题完全相同

      我所做的是为微调器添加一个自定义主题

       <Spinner
                      android:id="@+id/spinner1"
                      android:layout_width="match_parent"
                      android:layout_height="30sp"
                      android:entries="@array/guest_type"
                      android:prompt="@string/guesttype"
                      android:theme="@style/AppTheme1"   />
      

      styles.xml

        <style name="AppTheme1" parent="Theme.AppCompat.Light">
          <item name="android:spinnerDropDownItemStyle">@style/mySpinnerItemStyle</item>
      </style>
      
      <style name="mySpinnerItemStyle" parent="@android:style/Widget.Holo.DropDownItem.Spinner">
          <item name="android:textColor">#000000</item>
      </style>
      

      【讨论】:

      • sp 是文本大小,所以 => android:layout_height="30dp" 或更好的 android:layout_height="@dimen/my_size"
      【解决方案9】:

      在微调器中使用 android:dropDownVerticalOffset 属性来提供与顶部的间距。

      <Spinner
              android:id="@+id/spnrLanguage"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_marginTop="5dp"
              android:background="@drawable/ic_dropdown"
              android:padding="5dp"
              android:spinnerMode="dropdown"
              android:dropDownVerticalOffset="50dp"
              />
      

      别忘了设置 android:spinnerMode="dropdown" 虽然它在 spinnerMode= dialog

      中不起作用>

      【讨论】:

        【解决方案10】:

        对于正确的微调器图标着色,您也可以从代码中为微调器充气:

        spinner_toolbar.xml:

        <?xml version="1.0" encoding="utf-8"?>
        <Spinner xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/spinner_toolbar"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"/>
        

        然后您必须将 Spinner 附加到 Activity 中的工具栏:

        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getSupportActionBar().getThemedContext(),
                    R.array.planets_array, R.layout.support_simple_spinner_dropdown_item);
        adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        
        // we inflate the spinner with the themed Toolbar context -> correct icon tinting
        LayoutInflater.from(getSupportActionBar().getThemedContext()).inflate(R.layout.spinner_toolbar, tb, true);
        
        Spinner spinner = (Spinner) toolbar.findViewById(R.id.spinner_toolbar);
        spinner.setAdapter(adapter);
        

        但是,这对整个 Spinner 使用 app:theme 而不是 app:popupTheme,包括下拉菜单。 因此,微调器图标和文本将正确着色,但下拉菜单也具有工具栏的样式,而不是 popupTheme 的样式。

        因此,如果您想要一个深色工具栏和一个浅色下拉菜单,则需要以某种方式修复下拉样式,例如通过为微调器创建一个自定义样式,该样式指定一个白色背景和一个带有深色文本颜色。

        也许其他人对如何将 app:popupTheme 传播到 Spinner 下拉菜单有更好的解决方案。

        【讨论】:

          【解决方案11】:

          您可以使用以下代码修复 Android 4 的下拉位置(将显示在工具栏顶部,如菜单):

          <Spinner
                  android:id="@+id/spinner"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:dropDownVerticalOffset="-56dp"/>
          

          【讨论】:

            【解决方案12】:

            为了解决这个问题,我遇到了类似的问题。我的主要问题是工具栏中的文本小于通常的标题尺寸和错误的颜色。截图在这里http://s27.postimg.org/v24x1aw43/Screen_Shot_2015_01_11_at_13_36_04.png

            下拉菜单没问题,但我也会对其进行自定义。

            我还要澄清一下,这个修复主要基于@Daniel B 的修复,但不需要自定义适配器,据我所知没有任何问题,但我不保证!

            1. 将普通微调器项添加到 XML 布局文件中(在工具栏中)。
            <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:elevation="5dp"
                    android:minHeight="?attr/actionBarSize"
                    android:background="@color/colorPrimary"
                    app:theme="@style/GalaxyZooThemeToolbarDarkOverflow"
                    app:popupTheme="@style/Theme.AppCompat"
                    >
            
                <Spinner
                    android:id="@+id/spinner_nav"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            
            
                </android.support.v7.widget.Toolbar>
            
            1. 创建新的布局文件 toolbar_spinner_item_actionbar.xml(这将是工具栏中微调器显示的内容)
            <?xml version="1.0" encoding="utf-8"?>
            
            <TextView
                android:id="@android:id/text1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawablePadding="20dp"
                android:fontFamily="sans-serif"
                android:paddingLeft="@dimen/abc_action_bar_default_padding_material"
                android:paddingRight="4dp"
                android:textColor="@color/colorDark"
                android:textSize="@dimen/abc_text_size_title_material_toolbar"
                xmlns:android="http://schemas.android.com/apk/res/android"/>
            
                <!-- android:drawableRight="@drawable/spinner_triangle" -->
            
            1. 微调器的适配器几乎保持不变,但是将布局从标准 android.R.layout.simple_spinner_dropdown_item 切换到 R.layout.toolbar_spinner_item_actionbar。这将应用您对工具栏文本的自定义外观。

            在此示例中,我将 adapter.setDropDownViewResource 设置为 android.R.layout.simple_spinner_dropdown_item,这会为下拉列表应用标准主题默认值,对此我很满意。

            ArrayAdapter<String> set1Adapter = new ArrayAdapter<String>(RoutineDetailsActivity.this, R.layout.toolbar_spinner_item_actionbar, set1Actual);
                    set1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            
                    mWeekSpinner.setAdapter(set1Adapter);
            

            基本上就是这样,结果在这里[无法附加图片或添加另一个链接,因为我的代表太低了!将在评论中添加] .您可以在这里停下来,但是您可能想要更改下拉箭头的颜色。

            从技术上讲,这对我的应用来说是正确的颜色,但是,由于我的原色已经是工具栏的颜色,自定义箭头是有意义的。

            设置自定义箭头可绘制

            1. 将这条可绘制线'android:drawableRight="@drawable/spinner_triangle'添加到之前制作的toolbar_spinner_item_actionbar.xml中。现在这可以是任何图像,现在你可以在这里使用Daniel B的白色箭头资源https://raw.githubusercontent.com/google/iosched/master/android/src/main/res/drawable-xxhdpi/spinner_triangle.png

            运行这将产生两个箭头,白色箭头和主题默认值。要解决此问题,请添加以下样式。再次,这是从 Daniel B 的代码中提取的,可能会被删节,但现在它可以工作....

                <style name="Widget.MyApp.HeaderBar.Spinner" parent="Widget.AppCompat.Light.Spinner.DropDown.ActionBar">
                    <item name="android:background">?android:selectableItemBackground</item>
                    <item name="android:dropDownSelector">?android:selectableItemBackground</item>
                    <item name="android:divider">@null</item>
                    <item name="android:overlapAnchor">true</item>
                </style>
            
            1. 将创建的样式应用到微调器...
            <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:elevation="5dp"
                    android:minHeight="?attr/actionBarSize"
                    android:background="@color/colorPrimary"
                    app:theme="@style/GalaxyZooThemeToolbarDarkOverflow"
                    app:popupTheme="@style/Theme.AppCompat"
                    >
            
                <Spinner
                    android:id="@+id/spinner_nav"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    style="@style/Widget.MyApp.HeaderBar.Spinner"/>
            
            
                </android.support.v7.widget.Toolbar>
            

            结果将是这样的[再次无法附加或链接,将添加到评论]。可以从前面的文件设置中设置填充,在我的情况下,我需要更改箭头以匹配图标。

            希望这有点道理。

            【讨论】:

            【解决方案13】:

            当我使用微调器时它崩溃了(Android 2.3.3 - 2.3.7)。

            所以我现在尝试使用 TintSpinner,它没有崩溃,试试你自己作为可选解决方案

             <?xml version="1.0" encoding="utf-8"?>
                <LinearLayout
                    xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:orientation="vertical">
            
                    <android.support.v7.internal.widget.TintSpinner
                        android:id="@+id/toolbar_spinner"
                        style="@style/HeaderBar.Spinner"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"/>
                </LinearLayout>
            

            并使用下面的代码来投射你的工具栏

             View spinnerContainer = LayoutInflater.from(this).inflate(R.layout.toolbar_spinner, toolbarTop, false);
                    ActionBar.LayoutParams lp = new ActionBar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
                    toolbarTop.addView(spinnerContainer, lp);
            
                    ToolBarSpinnerAdapter spinnerAdapter = new ToolBarSpinnerAdapter(getLayoutInflater());
                    String[] items = getResources().getStringArray(R.array.action_dropdown);
                    spinnerAdapter.addItems(items);
            
                    TintSpinner mNavigationSpinner = (TintSpinner) spinnerContainer.findViewById(R.id.toolbar_spinner);
                    mNavigationSpinner.setAdapter(spinnerAdapter);
            

            【讨论】:

            • 我不鼓励任何人使用这种方法。 TintSpinner 是一个内部小部件,它很快就会改变。这个想法是将内部小部件作为公共小部件发布,因此 API 将受到一些修改(例如,TintSpinner 将被简称为 Spinner)。请不惜一切代价避免使用此方法,除非您打算坚持使用当前的 AppCompat 库版本及其所有错误
            • @mradzinski,感谢您解释的答案,但是当我使用 Spinner 时,我的应用程序崩溃了(Android 2.3.3 - 2.3.7)。但是当我使用 TintSpinner 时,它并没有崩溃(Android 2.3.3 - 2.3.7)。我还是不明白为什么会这样,在这里我只是尝试给出一个可选的解决方案。
            【解决方案14】:

            我在这个问题上浪费了很多时间。据我所知,上述解决方案都需要复制/粘贴大量 appcompat 样式代码来重新实现触摸状态等基本细节。

            获得类似原生行为的一种相对简单的方法是以编程方式扩展视图以确保它获得正确的主题,例如:

            // Activity has context with 'Theme.AppCompat.Light.NoActionBar'
            spinner = new AppCompatSpinner(getActivity());
            toolbar.addView(spinner);
            

            为了使三角形变为白色而不是 colorControlNormal,我在背景上应用了 ColorStateList 色调:

            ViewCompat.setBackgroundTintList(spinner, resources.getColorStateList(R.drawable.bg_toolbar_spinner)
            

            bg_toolbar_spinner.xml

            <selector xmlns:android="http://schemas.android.com/apk/res/android">
                <item android:color="@color/accent" android:state_pressed="true"/>
                <item android:color="@android:color/white"/>
            </selector>
            

            【讨论】:

              【解决方案15】:

              我通过为版本 21 和 23 创建新值并在微调器样式 android:dropDownVerticalOffset 中添加新属性并从默认样式文件中删除它来解决它。 (我的情况与工具栏无关)适用于普通微调器。

              在文件夹 23 和 21 中添加此样式

              <style name="spinner_style">
                  <item name="android:background">@drawable/background_spinner</item>
                  <item name="android:dropDownVerticalOffset">30dip</item>
              </style>
              

              它在所有版本上都能完美运行。希望这对你有用!

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多