Как я могу исправить стиль Spinner для Android 4.x, размещенный поверх панели инструментов

Согласно документации Android, виджет 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 spinner и раскрывающийся список выглядят нормально, хотя цвет фона раскрывающегося списка черный по сравнению с раскрывающимся меню, которое белое. Я предполагаю, что 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 с черным фоном и белым текстом, но я думаю, что это можно решить с помощью пользовательского макета. Если никто не даст полный ответ, я сделаю это сам и отмечу как принятый.


person Damian Petla    schedule 05.11.2014    source источник
comment
попробуйте использовать getSupportActionBar().getThemedContext() вместо mToolbar.getContext()   -  person Selvin    schedule 05.11.2014
comment
@Selvin Я уже пробовал это. Это выглядит точно так же   -  person Damian Petla    schedule 05.11.2014
comment
@Loop У меня такая же проблема, ты когда-нибудь находил решение?   -  person Nathan Walters    schedule 14.11.2014
comment
для значка счетчика может помочь это.   -  person turtle    schedule 14.11.2014
comment
@Loop Я боролся с тем же самым и обнаружил, что обновление AppCompat с 21.0.0 до 21.0.2 исправило цвет значка фильтра счетчика. Я решил другие проблемы, используя пользовательские макеты.   -  person Andrey Makarov    schedule 08.12.2014
comment
Как вы заставили это скомпилировать что-то ниже с SDK ниже 21? Я пытался использовать панель инструментов, и eclipse требовал, чтобы minsdk был 21, как только я установил, что он не будет компилироваться ни на чем, кроме 21. Можете ли вы опубликовать свой манифест?   -  person Sauron    schedule 14.12.2014
comment
Как я могу разрешить совместимость вкладок с Android 4 и 5?   -  person Sauron    schedule 14.12.2014
comment
Привет, Все еще сталкиваюсь с той же проблемой, хотя я следовал всем вашим инструкциям. Даже если я удалил значок фильтра, я получаю только черный фон.   -  person Ashokchakravarthi Nagarajan    schedule 31.01.2015
comment
см. этот аналогичный вопрос stackoverflow.com/questions/26852108/   -  person Glogo    schedule 06.02.2015


Ответы (15)


Я знаю, что уже поздно, но я столкнулся с этим вопросом, когда сам столкнулся с этой проблемой, и нашел решение в BrowseSessionsActivity ссылки приложение Google I/O 2014 и адаптировал его.

Макеты

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_triangle можно найти здесь. .

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

Результат

Спиннер материалов

KitKat Spinner

person Dan    schedule 02.01.2015
comment
Еще не поздно :). Я хотел бы добавить, что toolbar_spinner.xml не является обязательным. Вы можете поместить ‹Spinner /› внутрь ‹Toolbar /›. Таким образом, вам не нужно надувание контейнера и дополнительная возможность рисования. Spinner будет использовать drawable по умолчанию. - person bajicdusko; 28.02.2015
comment
getLayoutInflater() не распознается, как получить LayoutIinflater в BaseAdapter? - person Mendhak; 01.03.2015
comment
Я думаю, что это не удается на Gingerbread с: ... Вызвано: android.content.res.Resources $ NotFoundException: ресурс не является Drawable (цвет или путь): TypedValue {t = 0x2/d = 0x101030e a = 2} и 0x101030e кажется developer.android.com/reference/android/ - удаление использования ?android:selectableItemBackground в styles.xml приводит к некоторым проблемам с пользовательским интерфейсом. - person aleb; 02.03.2015
comment
Это плохо работает на лолипопе. Фон там темный :/ - person Jacek Kwiecień; 05.03.2015
comment
Лучше использовать ?attr/selectableItemBackground вместо ?android:selectableItemBackground, чтобы выбранное состояние не отображалось синим на устройствах до kitkat. - person Huby; 16.04.2015
comment
@Xylian: добавьте android:theme="@style/ThemeOverlay.AppCompat.Light" в свой компонент счетчика, это исправило это для меня. Я отредактировал ответ, отражающий мои последние два комментария. - person Huby; 20.04.2015
comment
кто-нибудь знает, как отключить счетчик для определенного фрагмента? в onDetach() я использовал spinner.setVisibility(View.INVISIBLE); работает нормально, но фрагмент перезапускается в NavigationDrawer spinner.setVisibility(View.VISIBLE);< /i> не работает !! Не удалось повторно включить счетчик, который вводится в Toolbar!! любые решения? К вашему сведению, я пытаюсь отключить счетчик на панели инструментов в другом макете в панели навигации! - person LOG_TAG; 15.07.2015
comment
Я получил эту ошибку, android:overlapanchor requires api 21 (current min is 15). Это правда? Это работает только при минимальном API 21 и выше? - person Rock Lee; 23.10.2015
comment
@RockLee Приложение по-прежнему будет компилироваться и будет использоваться только в API 21, вы можете оставить его как есть или создать другой layout-v21, если хотите избавиться от ошибки. - person Dan; 23.10.2015
comment
При использовании в NavigationDrawer я сделал это, раздув представление счетчика в DrawerActivity и установив общедоступный статический счетчик Spinner; ссылаться на другие фрагменты. Чтобы очистить счетчик или отключить, вам нужно удалить панель инструментов в вашем конкретном фрагменте, прикрепить новую новую панель инструментов. Это оно - person EngineSense; 24.12.2015
comment
Ответ божественный и Непорочный! Большое спасибо! Я становлюсь более понимающим, когда дело доходит до материального дизайна. Я думал, что это просто набор виджетов, но оказалось, что это руководства о том, как сделать так, чтобы это выглядело так, используя существующие виджеты. Я просто действительно нахожу это слишком громоздким и надеялся, что они просто добавили его как элементы xml и покончили с этим. Например, я написал свой собственный макет для разделителя с подзаголовком. Боюсь, со всеми этими вопросами вскоре мне, возможно, придется реализовать это аналогично другим виджетам, не похожим на леденцы. - person Neon Warge; 15.04.2016
comment
Ссылка для рисования spinner_triangle не работает. Не могли бы вы обновить эту часть? - person S. Czop; 15.02.2019

Не внедряйте Spinner в 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);

Таким образом, значок рядом со счетчиком будет белым.

person user3461233    schedule 05.12.2014
comment
ЭТО Путь! - person Langusten Gustel; 20.11.2015

Извините за мой плохой английский. :) Я думаю, что лучше сразу создать счетчик в панели инструментов.

Вот пример в моем фрагменте.

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 все выглядит нормально: android-4.1-spinner

person Miao1007    schedule 09.11.2014
comment
Спасибо за ваш ответ, я попробую. Однако я считаю, что использование внутренних реализаций виджетов не является хорошей идеей, поскольку они могут быть изменены в appcompat без дополнительного уведомления. Кроме того, в полном решении я ожидаю, что всплывающее окно счетчика будет выглядеть как всплывающее окно из Settins (белый фон с белым текстом). - person Damian Petla; 09.11.2014
comment
Как вы скомпилировали это на Android 4.1? При использовании ToolBar это заставляет меня установить для minSDK значение 21 и, следовательно, не будет компилироваться на чем-либо ниже - person Sauron; 15.12.2014
comment
TintSpinner — это внутренний виджет, который будет меняться. Идея состоит в том, чтобы внутренние виджеты выпускались как общедоступные, поэтому API претерпит несколько модификаций (например, TintSpinner будет называться просто Spinner). Пожалуйста, избегайте использования этого метода любой ценой, если вы не планируете использовать текущую версию библиотеки AppCompat и все ее ошибки. - person mradzinski; 10.02.2015
comment
Этих классов нет в appcompat v22.2. - person LOG_TAG; 15.07.2015
comment
Сделав это mToolbar.removeView(mSpinner);, сможете ли вы снова просмотреть его на Панели инструментов? (при использовании во фрагменте навигационного ящика) - person LOG_TAG; 16.07.2015
comment
@LOG_TAG Он предназначен для навигационного ящика, вы не увидите счетчик, когда измените его на другой фрагмент. - person Miao1007; 16.07.2015
comment
@ Мяо1007 да !! но не удалось снова сделать видимым, когда тот же фрагмент снова щелкнут, я ввел макет счетчика на панель инструментов toolbar.addView(spinnerContainer, lp); (см. Daniel B Ans), в этом случае он не работает , опубликуйте ссылку на код github очень скоро, спасибо - person LOG_TAG; 16.07.2015
comment
@LOG_TAG о.... Вот пример код, удачи. - person Miao1007; 16.07.2015

Я борюсь с точно такой же проблемой.

Попробуйте изменить ресурс раскрывающегося списка. По крайней мере, это решило проблему с цветом текста для меня, однако цвет значка стрелки по-прежнему темный. Так что это всего лишь частичное обходное решение.

setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
person Sven    schedule 05.11.2014
comment
Я уже пробовал это с половинчатым успехом. В любом случае, я ищу полное решение. У меня действительно есть идея попробовать. Я опубликую это здесь, если это сработает. - person Damian Petla; 05.11.2014
comment
Я обнаружил, что настройка «colorControlNormal» меняет значок фильтра на этот цвет. Однако это также изменяет другие элементы управления в содержимом приложения. Итак, теперь задача состоит в том, чтобы применить это свойство к счетчику на панели инструментов. Применение этого свойства к стилю панели инструментов ничего не дает. - person Damian Petla; 05.11.2014

Простой способ, не идеальный, но достаточно унифицированный как для 4.x, так и для 5.0.

img

Я удалил <Spinner> из файлов макета и добавил его программно, что позволило правильно отобразить белый треугольник.

Я также создал макет раскрывающегося списка, используя требуемый цвет 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 исправят эти проблемы (в любом случае, мы надеемся).

person Mendhak    schedule 01.03.2015

Я потратил два дня на эту проблему, но теперь, прочитав много ответов, я могу опубликовать свое решение. Я реализовал два пользовательских макета для элемента счетчика и всплывающего окна. Установка этого атрибута для счетчика: android:background="?android:selectableItemBackground" черная стрелка счетчика по умолчанию скрыта, и мы можем использовать то, что предпочитаем. Я использовал метод setDropDownVerticalOffset(int) для управления позицией всплывающего окна в версиях Android до Lollipop.

Глобальная тема моего приложения

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

Наконец, соответствующая часть исходного кода активности:

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

введите здесь описание изображениявведите здесь описание изображения введите здесь описание изображения

Надеюсь, поможет! :)

person dginelli    schedule 25.06.2015

Вы не можете этого сделать?

Пользовательский 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);

Затем удалите раскрывающийся ресурс.

person Lukos    schedule 12.11.2014
comment
Это не работает, как я ожидаю. Он просто меняет текстовую часть и выглядит ужасно плохо. Внешний вид может быть изменен, но значок фильтра остается неизменным. - person Damian Petla; 13.11.2014

Была такая же проблема со спиннером

Что я сделал, так это добавил пользовательскую тему для счетчика.

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

стили.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>
person coolswap11    schedule 08.12.2014
comment
sp для размера текста, поэтому =› android:layout_height=30dp или лучше android:layout_height=@dimen/my_size - person letroll; 24.05.2017

Используйте свойство 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

person Pranav    schedule 22.12.2015

Для правильного окрашивания значка Spinner вы также можете просто надуть счетчик из кода:

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 к панели инструментов в вашей деятельности:

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

Однако при этом используется app:theme вместо app:popupTheme для всего Spinner, включая раскрывающееся меню. Следовательно, значок и текст Spinner будут окрашены правильно, но выпадающее меню также имеет стиль панели инструментов, а не popupTheme.

Поэтому, если вы хотите иметь темную панель инструментов и светлое раскрывающееся меню, вам нужно как-то исправить стиль раскрывающегося списка, например, создав собственный стиль для счетчика с белым фоном и пользовательским раскрывающимся списком с темным цветом текста. .

Возможно, у кого-то есть лучшее решение о том, как app:popupTheme можно распространить в раскрывающемся меню Spinner.

person Alexander Oprisnik    schedule 27.11.2014

Вы можете исправить положение раскрывающегося списка (будет отображаться в верхней части панели инструментов, например меню) для Android 4, используя этот код:

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

Чтобы понять это, у меня были похожие проблемы. Моя главная проблема заключалась в том, что текст на моей панели инструментов был меньше, чем обычные размеры заголовка, и имел неправильный цвет. Скриншот здесь 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, созданный ранее. Теперь это может быть любое изображение, а пока вы можете использовать ресурс белой стрелки Даниэля Б здесь 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>

Результат будет примерно таким [опять же не могу прикрепить или дать ссылку, добавлю в комментарий]. Отступы можно установить из настройки файла ранее, в моем случае мне нужно было бы изменить стрелку, чтобы она соответствовала значкам.

Надеюсь, это имеет какой-то смысл.

person user1544797    schedule 11.01.2015
comment
Изображение 2 – s27.postimg.org/vhg6ubi1f/ Изображение 3 – s27.postimg.org/h9qi5o5cj/ - person user1544797; 11.01.2015

Когда я использовал счетчик, он разбился (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);
person IshRoid    schedule 05.02.2015
comment
Я обескураживаю любого, кто использует этот подход. TintSpinner — это внутренний виджет, и он скоро изменится. Идея состоит в том, чтобы внутренние виджеты выпускались как общедоступные, поэтому API претерпит несколько модификаций (например, TintSpinner будет называться просто Spinner). Пожалуйста, избегайте использования этого метода любой ценой, если вы не планируете использовать текущую версию библиотеки AppCompat и все ее ошибки. - person mradzinski; 10.02.2015
comment
@mradzinski, спасибо за ваш объясненный ответ, но когда я использую Spinner, мое приложение разбилось (Android 2.3.3 - 2.3.7). Но когда я использовал TintSpinner, он не зависал (Android 2.3.3 - 2.3.7). Тем не менее я не понял, почему это происходит, здесь я просто пытаюсь дать необязательное решение. - person IshRoid; 11.02.2015

Я потратил часы на эту проблему. Насколько я могу судить, все приведенные выше решения требуют копирования/вставки больших фрагментов кода в стиле 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>
person user3452758    schedule 17.07.2015

Я решил это, создав новые значения для версий 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>

Он отлично работает на всех версиях. Надеюсь, это работает с вами!

person Ibrahim AbdelGawad    schedule 27.03.2016