android developer android developer - 4 years ago 275
Android Question

How to add dividers between specific menu items?

Background



I have a menu item in the action bar (toolbar actually) that when clicked, shows a list of items to choose from, similar to radio-buttons:

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


I need to put an item below this list of items, that will have a divider between it and the list. Similar to what the material design guidelines show (taken from here) :

enter image description here

EDIT: here's a sketch of what I want to do:

enter image description here

The problem



I can't find a way to do it.

What I've tried



The only possible solutions I've found are:


  1. change the theme of the activity (here), but this will also affect other menu items of the activity

  2. methods to put a divider between menu items when they appear on the action bar, but here they do not appear on the toolbar itself. They appear on a popup menu of a selected item.

  3. I tried to put fake items between the list and the extra item, and I also tried to put a group, an empty group and even tried various attributes.



Sadly nothing worked.

The question



How can I add a divider between specific items of an action-item's popup menu ?

Perhaps I need to create a custom popup menu when clicking on the action item (like here) ? If so, how do I put a divider between specific items there ?
Maybe use a Spinner as an action item?

Answer Source

OK, I've found a nice workaround, but I'm not sure the styling should be this way. That's what I'm missing:

  1. background of items is on top of the background of the popup of the spinner, and I'm not sure if that's the correct way to put it.
  2. I used the white background of the support library for the popup of the spinner. I think there should be a better way to make it white.
  3. I need to know what is the correct style of the divider. for now I used a simple one
  4. Action bar item style is missing. I just used a simple ImageView, and I think it should be different.
  5. For some reason, on some Android versions (maybe Lollipop and below) the background of the items look black instead of white.
  6. The spinner might sometimes have issues with setOnItemSelectedListener , not sure when.

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/layout/spinner.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/values/styles.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/divider.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>
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download