How can I fix the Spinner style for Android 4.x placed on top of the Toolbar

后端 未结 15 717
别那么骄傲
别那么骄傲 2020-12-04 06:10

According to Android documentation, Material Design style is supported for Spinner widget.

So I decided to use it in my app placing it on top of the Toolbar.

<

相关标签:
15条回答
  • 2020-12-04 06:36

    Don't implement Spinner in Xml

    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);
    

    This way the icon next to spinner will be white

    0 讨论(0)
  • 2020-12-04 06:39

    I've wasted hours on this issue. As far as I can tell, the above solutions all require copy/pasting large chunks of appcompat style code to reimplement basic details like touch states.

    A relatively easy way to get native-like behaviour is to inflate the view programmatically to ensure it gets the correct theme, e.g.:

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

    To get the triangle to be white rather than colorControlNormal, I've applied a ColorStateList tint to the background:

    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>
    
    0 讨论(0)
  • 2020-12-04 06:42

    I spent two days on this problem, but now after reading many answers, I can post my solution. I've implemented two custom layouts for the spinner item and popup. Setting this attribute for spinner: android:background="?android:selectableItemBackground" the default spinner black arrow is hidden and we can use what we prefer. I used the method setDropDownVerticalOffset(int) to manage the popup position on pre Lollipop Android versions.

    My app global theme is

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

    Now, the activity layout that contains the toolbar and the spinner:

    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) : "";
       }
    }
    

    Finally, the relevant part of activity source code:

    @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);
        }
    }
    

    These are the results on Lollipop and Kitkat:

    enter image description here enter image description here enter image description here

    Hope it helps! :)

    0 讨论(0)
  • 2020-12-04 06:43

    Can you not do this?

    Custom xml file for spinner item: 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"
        />
    

    Use this to show spinner items:

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

    Then remove drop down resource.

    0 讨论(0)
  • 2020-12-04 06:43

    Use android:dropDownVerticalOffset property inside spinner to give spacing from top.

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

    Don't forgot to set android:spinnerMode="dropdown" though it won't work in spinnerMode= dialog

    0 讨论(0)
  • 2020-12-04 06:43

    You can fix dropdown position (will show on the top of toolbar, like menu) for Android 4 using this code:

    <Spinner
            android:id="@+id/spinner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:dropDownVerticalOffset="-56dp"/>
    
    0 讨论(0)
提交回复
热议问题