Как добавить разделители между конкретными пунктами меню?

фон

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

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:icon="@drawable/..."
        android:title="@string/..."
        app:showAsAction="always">
        <menu>
            <group
                android:id="@+id/..."
                android:checkableBehavior="single">
                <item .../>
                <item .../>
                <item .../>
            </group>
        </menu>
    </item>
</menu>

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

enter image description here

EDIT: вот эскиз того, что Я хочу сделать:

enter image description here

проблема

Я не могу найти способ сделать это.

что я пробовал

единственные возможные решения, которые я нашел:

  1. изменить тему работы (здесь), но это также повлияет на другие пункты меню активности

  2. методы для размещения разделителя между пунктами меню, когда они появляются на панель действий, но здесь они не отображаются на панели инструментов. Они появляются во всплывающем меню выбранного элемента.

  3. Я попытался поместить поддельные элементы между списком и дополнительным элементом, а также попытался поместить группу, пустую группу и даже попробовал различные атрибуты.

к сожалению, ничего не получалось.

вопрос

как добавить разделитель между конкретными пунктами всплывающего меню элемента действия ?

возможно, мне нужно создать пользовательское всплывающее меню при нажатии на элемент действия (например,здесь) ? Если да, то как я могу поместить разделитель между конкретными элементами там ? Может быть, использовать Spinner в качестве элемента действия?

6 ответов


вы должны использовать макет действия

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".LandingActivity">
    <item
        android:id="@+id/action_cart"
        android:title="cart"
        android:actionLayout="@layout/cart_update_count"
        android:icon="@drawable/shape_notification"
        app:showAsAction="always"/>
</menu>

и тогда макет действия может иметь textview с разделителем.

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/divider"/>

    <TextView
        android:id="@android:id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:gravity="center_vertical"          
        android:textAppearance="?attr/textAppearanceListItemSmall"/>

</LinearLayout>

затем вы можете добавить прослушиватель кликов в code


хорошо, я нашел хороший обходной путь, но я не уверен, что стиль должен быть таким. Вот чего мне не хватает:

  1. фон элементов находится поверх фона всплывающего окна блесны, и я не уверен, что это правильный способ поставить его.
  2. я использовал белый фон библиотеки поддержки для всплывающего окна счетчика. Я думаю, должен быть лучший способ сделать его белым.
  3. мне нужно знать, что правильный стиль делитель. пока я использовал простой
  4. стиль элемента панели действий отсутствует. Я просто использовал простой ImageView, и я думаю, что он должен быть другим.
  5. по какой-то причине в некоторых версиях Android (возможно, Lollipop и ниже) фон элементов выглядит черным, а не белым.
  6. spinner может иногда иметь проблемы с setOnItemSelectedListener , не уверен, когда.

MainActivity

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    final MenuItem item = menu.findItem(R.id.action_settings);
    final Spinner spinner = ((Spinner) MenuItemCompat.getActionView(item));
    SimpleImageArrayAdapter adapter = new SimpleImageArrayAdapter(this);
    spinner.setAdapter(adapter);
    return true;
}

public class SimpleImageArrayAdapter extends ArrayAdapter<String> {
    private final String[] items = {"item 1", "item 2", "item 3", "extra item"};

    public SimpleImageArrayAdapter(Context context) {
        super(context, 0);
    }

    @Override
    public int getCount() {
        return items.length;
    }

    @Override
    public String getItem(final int position) {
        return items[position];
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        View rootView = convertView == null ? LayoutInflater.from(getContext()).inflate(R.layout.spinner_item, parent, false) : convertView;
        TextView tv = (TextView) rootView.findViewById(android.R.id.text1);
        tv.setTextColor(0xff000000);
        tv.setText(items[position]);
        boolean isLastItem = position == getCount() - 1;
        rootView.findViewById(R.id.action_divider).setVisibility(isLastItem ? View.VISIBLE : View.GONE);
        rootView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        return rootView;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //this is the view that's shown for the spinner when it's closed
        ImageView iv = new ImageView(getContext());
        iv.setImageResource(android.R.drawable.ic_menu_add);
        int viewSize = getDimensionFromAttribute(MainActivity.this, android.support.v7.appcompat.R.attr.actionBarSize);
        iv.setLayoutParams(new ViewGroup.LayoutParams(viewSize, viewSize));
        iv.setScaleType(ScaleType.CENTER_INSIDE);
        iv.setBackgroundResource(getResIdFromAttribute(MainActivity.this, R.attr.selectableItemBackground));
        return iv;
    }

}

public static int getResIdFromAttribute(final Activity activity, final int attr) {
    if (attr == 0)
        return 0;
    final TypedValue typedValue = new TypedValue();
    activity.getTheme().resolveAttribute(attr, typedValue, true);
    return typedValue.resourceId;
}

public static int getDimensionFromAttribute(final Context context, final int attr) {
    final TypedValue typedValue = new TypedValue();
    if (context.getTheme().resolveAttribute(attr, typedValue, true))
        return TypedValue.complexToDimensionPixelSize(typedValue.data, context.getResources().getDisplayMetrics());
    return 0;
}

res / menu / menu_main.в XML

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      tools:context="com.example.user.myapplication.MainActivity">
    <item
        android:id="@+id/action_settings"
        android:actionLayout="@layout/spinner"
        android:title=""
        app:actionLayout="@layout/spinner"
        app:showAsAction="always"
        />
</menu>

res / layout / spinner_item.в 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">

    <ImageView
        android:id="@+id/action_divider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/divider"/>

    <TextView
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:gravity="center_vertical"
        android:minHeight="?attr/listPreferredItemHeightSmall"
        android:paddingEnd="?attr/listPreferredItemPaddingRight"
        android:paddingLeft="?attr/listPreferredItemPaddingLeft"
        android:paddingRight="?attr/listPreferredItemPaddingRight"
        android:paddingStart="?attr/listPreferredItemPaddingLeft"
        android:textAppearance="?attr/textAppearanceListItemSmall"/>

</LinearLayout>

res / макет / счетчик.в XML

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

res / значения / стили.в XML

<style name="SpinnerWithoutArrow" parent="@style/Widget.AppCompat.Spinner">
    <item name="android:background">@null</item>
    <item name="android:popupBackground">@drawable/abc_popup_background_mtrl_mult</item>
</style>

res / drawable / делитель.в XML

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:height="1dp"/>
    <solid android:color="#FFff0000" />
</shape>

Я сделал это так:

ссылка скриншот:

enter image description here

стиль.XML-код:

    <style name="popup" parent="Widget.AppCompat.ListView.DropDown">
            <item name="android:divider">@color/colorPrimary</item>
            <item name="android:dividerHeight">1dp</item>
            <item name="android:textColor">@color/colorPrimary</item>
            <item name="android:itemBackground">@android:color/white</item>
    </style>

 <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

        <!--- Customize popmenu -->
        <item name="android:dropDownListViewStyle">@style/popup</item>


    </style>

Java-кода:

private void showPopup(View v) {
        Context wrapper = new ContextThemeWrapper(this, R.style.popup);
        PopupMenu mypopupmenu = new PopupMenu(wrapper, v);
        MenuInflater inflater = mypopupmenu.getMenuInflater();
        inflater.inflate(R.menu.menu_patient_language, mypopupmenu.getMenu());
        mypopupmenu.show();
        mypopupmenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                txtPreferredLanguage.setText(item.getTitle().toString());
                switch (item.getItemId()) {
                    case R.id.menuEnglish:
                        // Your code goes here
                        break;

                    case R.id.menuFrench:
                        // Your code goes here
                        break;
                }
                return false;
            }
        });
    }

надеюсь, это поможет вам.


Это можно сделать с помощью всплывающего окна и посмотреть список. В представлении списка можно использовать различные типы представлений, такие как пункт меню и разделитель.

я перечисляю код для части всплывающего окна:

    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.option_menu, null);
    ListView listView = (ListView) view.findViewById(R.id.listView);
    listView.setDivider(null);

    mAdapter = new OptionListAdapter(context, options);
    listView.setAdapter(mAdapter);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //TODO: The code when item is clicked.
        }
    });

    mPopupWindow = new PopupWindow(context, null, R.attr.popupMenuStyle);
    mPopupWindow.setFocusable(true); // otherwise on android 4.1.x the onItemClickListener won't work.
    mPopupWindow.setContentView(view);
    mPopupWindow.setOutsideTouchable(true);

    int height = 0;
    int width = 0;
    float density = context.getResources().getDisplayMetrics().density;
    int minWidth = Math.round(196 * density); // min width 196dip, from abc_popup_menu_item_layout.xml
    int cellHeight = context.getResources().getDimensionPixelOffset(R.dimen.option_height);
    int dividerHeight = context.getResources().getDimensionPixelOffset(R.dimen.divider_height);
    final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    for (int i = 0; i < mAdapter.getCount(); i++) {
        Object item = mAdapter.getItem(i);
        if (item != null) {
            View childView = mAdapter.getView(i, null, listView);
            childView.measure(widthMeasureSpec, heightMeasureSpec);
            height += cellHeight;
            width = Math.max(width, childView.getMeasuredWidth());
        } else {
            height += dividerHeight; // divider
        }
    }
    width = Math.max(minWidth, width);
    Drawable background = mPopupWindow.getBackground(); // 9-pitch images
    if (background != null) {
        Rect padding = new Rect();
        background.getPadding(padding);
        height += padding.top + padding.bottom;
        width += padding.left + padding.right;
    }
    mPopupWindow.setWidth(width);
    mPopupWindow.setHeight(height);
    mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);

затем вы можете использовать следующий метод для отображения всплывающего окна:

PopupWindowCompat.showAsDropDown(mPopupWindow, parent, x, y, gravity);

в адаптере для представления списка вы можете переопределить getViewTypeCount () и getItemViewType () для поддержки макета элементов меню и макета разделителя, а также добавить любой тип представления, который тебе нужно.

вот снимок в моем приложении:

enter image description here


супер простое решение, которое сработало для меня:

определите drawable для фона:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@android:color/white"/>
    <stroke
        android:width="3dp"
        android:color="@color/colorPrimary"/>

</shape>

затем в стилях используйте фон:

<style name="bluetooth_popup" parent="@android:style/Widget.DeviceDefault.Light.PopupMenu">
    <item name="android:textColor">@color/colorPrimary</item>
    <item name="android:textStyle">bold</item>
    <item name="android:textAllCaps">true</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:itemBackground">@drawable/bluetooth_popup_buttons</item>

теперь :

group1[ item0 item1 item2 ] group1[item3];

заменить на :

group1[ item0 item1] group1[item2 item3]

группы divider; ему нравится, что группа может добавить divder между item;

если divider недоступна,попробуйте background; я никогда не пользователь menu; это моя догадка;