Question

I have the following Android menu XML file:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/programma"
          android:icon="@android:drawable/ic_menu_agenda"
          android:title="@string/programma" />
    <item android:id="@+id/settings"
          android:icon="@android:drawable/ic_menu_preferences"
          android:title="@string/settings" />
    <item android:id="@+id/help"
          android:icon="@android:drawable/ic_menu_help"
          android:title="@string/help" />
</menu>

That gives me three menu buttons on one line. However, I want to divide them in two lines, with 2 buttons on the first row, and the help button on the entire bottom row. I already tried grouping the first two, but that didn't do the trick. How can I force a line break in the XML?

Was it helpful?

Solution

As far as I know there is no way to force line break in menu. This actually makes sense if you consider some scenarios.

For example, imagine you have tablet (for example, Galaxy Tab) in landscape orientation. It has quite a lot of horizontal space and relatively small height. So, it would be a waste of space if you force line break in such case.

enter image description here


I've done more investigation on this. There is a class called MenuBuilder which is used to manage options menu. It uses icon_menu_layout layout resource to draw menus. Here is this resource:

<com.android.internal.view.menu.IconMenuView
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+android:id/icon_menu"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:rowHeight="66dip"
   android:maxItems="6"
   android:maxRows="2"
   android:maxItemsPerRow="6" />

And if you follow to IconMenuView implementation, you'll find one interesting function called layoutItems which is used to calculate layout for menu items. You can only influence this function's logic by artificially increasing width of menu items. No line breaks are available.

private void layoutItems(int width) {
    int numItems = getChildCount();
    if (numItems == 0) {
        mLayoutNumRows = 0;
        return;
    }

    // Start with the least possible number of rows
    int curNumRows =
            Math.min((int) Math.ceil(numItems / (float) mMaxItemsPerRow), mMaxRows);

    /*
     * Increase the number of rows until we find a configuration that fits
     * all of the items' titles. Worst case, we use mMaxRows.
     */
    for (; curNumRows <= mMaxRows; curNumRows++) {
        layoutItemsUsingGravity(curNumRows, numItems);

        if (curNumRows >= numItems) {
            // Can't have more rows than items
            break;
        }

        if (doItemsFit()) {
            // All the items fit, so this is a good configuration
            break;
        }
    }
}

So, for example, if you increase width of first item, you'll get two lines in menu. But this is probably undesirable, because you can't predict text style, size and font that will be used on different devices.

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top