Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2d7a5d8 authored by Adam Powell's avatar Adam Powell
Browse files

Fix bug 3426162 - Overflow menu closes on its own

Makes populating action menus smarter, doesn't completely empty and
repopulate. Fixes issues where changing menus can leave popups without
an anchor.

Change-Id: I03cc266f0952123c5704a78cdcfc69b77af1915b
parent e44e28fa
Loading
Loading
Loading
Loading
+90 −26
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.view.Gravity;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -193,61 +192,125 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
        menu.setActionWidthLimit(width);

        menu.setMaxActionItems(mMaxItems);
        final boolean cleared = mMenu != menu;
        mMenu = menu;
        updateChildren(true);
        updateChildren(cleared);
    }

    public void updateChildren(boolean cleared) {
        final boolean reserveOverflow = mReserveOverflow;
        removeAllViews();
        
        final ArrayList<MenuItemImpl> itemsToShow = mMenu.getActionItems(reserveOverflow);
        final ArrayList<MenuItemImpl> itemsToShow = mMenu.getActionItems(mReserveOverflow);
        final int itemCount = itemsToShow.size();
        
        boolean needsDivider = false;
        int childIndex = 0;
        for (int i = 0; i < itemCount; i++) {
            final MenuItemImpl itemData = itemsToShow.get(i);
            boolean hasDivider = false;

            if (needsDivider) {
                addView(makeDividerView(), makeDividerLayoutParams());
                if (!isDivider(getChildAt(childIndex))) {
                    addView(makeDividerView(), childIndex, makeDividerLayoutParams());
                }
                hasDivider = true;
                childIndex++;
            }

            View actionView = itemData.getActionView();

            if (actionView != null) {
                final ViewParent parent = actionView.getParent();
                if (parent instanceof ViewGroup) {
                    ((ViewGroup) parent).removeView(actionView);
                }
                addView(actionView, makeActionViewLayoutParams(actionView));
            View childToAdd = itemData.getActionView();
            boolean needsPreDivider = false;
            if (childToAdd != null) {
                childToAdd.setLayoutParams(makeActionViewLayoutParams(childToAdd));
            } else {
                ActionMenuItemView view = (ActionMenuItemView) itemData.getItemView(
                        MenuBuilder.TYPE_ACTION_BUTTON, this);
                view.setItemInvoker(this);
                if (i > 0 && !hasDivider && view.hasText() && itemData.getIcon() == null) {
                    addView(makeDividerView(), makeDividerLayoutParams());
                }
                addView(view);
                needsPreDivider = i > 0 && !hasDivider && view.hasText() &&
                        itemData.getIcon() == null;
                needsDivider = view.hasText();
            }
                childToAdd = view;
            }

        if (reserveOverflow) {
            if (mMenu.getNonActionItems(true).size() > 0) {
                if (itemCount > 0) {
                    addView(makeDividerView(), makeDividerLayoutParams());
            boolean addPreDivider = removeChildrenUntil(childIndex, childToAdd, needsPreDivider);

            if (addPreDivider) addView(makeDividerView(), childIndex, makeDividerLayoutParams());
            if (needsPreDivider) childIndex++;

            if (getChildAt(childIndex) != childToAdd) {
                addView(childToAdd, childIndex);
            }
            childIndex++;
        }

        final boolean hasOverflow = mOverflowButton != null && mOverflowButton.getParent() == this;
        final boolean needsOverflow = mReserveOverflow && mMenu.getNonActionItems(true).size() > 0;

        if (hasOverflow != needsOverflow) {
            if (needsOverflow) {
                if (mOverflowButton == null) {
                    OverflowMenuButton button = new OverflowMenuButton(mContext);
                    mOverflowButton = button;
                }
                addView(mOverflowButton);
                boolean addDivider = removeChildrenUntil(childIndex, mOverflowButton, true);
                if (addDivider && itemCount > 0) {
                    addView(makeDividerView(), childIndex, makeDividerLayoutParams());
                    childIndex++;
                }
                addView(mOverflowButton, childIndex);
                childIndex++;
            } else {
                removeView(mOverflowButton);
            }
        } else {
            if (needsOverflow) {
                boolean overflowDivider = itemCount > 0;
                boolean addDivider = removeChildrenUntil(childIndex, mOverflowButton,
                        overflowDivider);
                if (addDivider && itemCount > 0) {
                    addView(makeDividerView(), childIndex, makeDividerLayoutParams());
                }
                if (overflowDivider) {
                    childIndex += 2;
                } else {
                mOverflowButton = null;
                    childIndex++;
                }
            }
        }

        while (getChildCount() > childIndex) {
            removeViewAt(childIndex);
        }
    }

    private boolean removeChildrenUntil(int start, View targetChild, boolean needsPreDivider) {
        final int childCount = getChildCount();
        boolean found = false;
        for (int i = start; i < childCount; i++) {
            final View child = getChildAt(i);
            if (child == targetChild) {
                found = true;
                break;
            }
        }

        if (!found) {
            return needsPreDivider;
        }

        for (int i = start; i < getChildCount(); ) {
            final View child = getChildAt(i);
            if (needsPreDivider && isDivider(child)) {
                needsPreDivider = false;
                i++;
                continue;
            }
            if (child == targetChild) break;
            removeViewAt(i);
        }

        return needsPreDivider;
    }

    private static boolean isDivider(View v) {
        return v != null && v.getId() == com.android.internal.R.id.action_menu_divider;
    }

    public boolean showOverflowMenu() {
@@ -302,6 +365,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
        ImageView result = new ImageView(mContext);
        result.setImageDrawable(mDivider);
        result.setScaleType(ImageView.ScaleType.FIT_XY);
        result.setId(com.android.internal.R.id.action_menu_divider);
        return result;
    }

+2 −0
Original line number Diff line number Diff line
@@ -250,6 +250,8 @@ public class ActionBarView extends ViewGroup {
    }

    public void setMenu(Menu menu) {
        if (menu == mOptionsMenu) return;

        MenuBuilder builder = (MenuBuilder) menu;
        mOptionsMenu = builder;
        if (mMenuView != null) {
+1 −0
Original line number Diff line number Diff line
@@ -73,4 +73,5 @@
  <item type="id" name="fillInIntent" />
  <item type="id" name="rowTypeId" />
  <item type="id" name="up" />
  <item type="id" name="action_menu_divider" />
</resources>