Search in sources :

Example 1 with ActionMenuItemView

use of com.android.internal.view.menu.ActionMenuItemView in project android_frameworks_base by ResurrectionRemix.

the class ActionMenuPresenter method bindItemView.

@Override
public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
    itemView.initialize(item, 0);
    final ActionMenuView menuView = (ActionMenuView) mMenuView;
    final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
    actionItemView.setItemInvoker(menuView);
    if (mPopupCallback == null) {
        mPopupCallback = new ActionMenuPopupCallback();
    }
    actionItemView.setPopupCallback(mPopupCallback);
}
Also used : ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView)

Example 2 with ActionMenuItemView

use of com.android.internal.view.menu.ActionMenuItemView in project android_frameworks_base by ResurrectionRemix.

the class ActionMenuView method onMeasureExactFormat.

private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
    // We already know the width mode is EXACTLY if we're here.
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    final int widthPadding = getPaddingLeft() + getPaddingRight();
    final int heightPadding = getPaddingTop() + getPaddingBottom();
    final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding, ViewGroup.LayoutParams.WRAP_CONTENT);
    widthSize -= widthPadding;
    // Divide the view into cells.
    final int cellCount = widthSize / mMinCellSize;
    final int cellSizeRemaining = widthSize % mMinCellSize;
    if (cellCount == 0) {
        // Give up, nothing fits.
        setMeasuredDimension(widthSize, 0);
        return;
    }
    final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
    int cellsRemaining = cellCount;
    int maxChildHeight = 0;
    int maxCellsUsed = 0;
    int expandableItemCount = 0;
    int visibleItemCount = 0;
    boolean hasOverflow = false;
    // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
    long smallestItemsAt = 0;
    final int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() == GONE)
            continue;
        final boolean isGeneratedItem = child instanceof ActionMenuItemView;
        visibleItemCount++;
        if (isGeneratedItem) {
            // Reset padding for generated menu item views; it may change below
            // and views are recycled.
            child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
        }
        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
        lp.expanded = false;
        lp.extraPixels = 0;
        lp.cellsUsed = 0;
        lp.expandable = false;
        lp.leftMargin = 0;
        lp.rightMargin = 0;
        lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
        // Overflow always gets 1 cell. No more, no less.
        final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
        final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, itemHeightSpec, heightPadding);
        maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
        if (lp.expandable)
            expandableItemCount++;
        if (lp.isOverflowButton)
            hasOverflow = true;
        cellsRemaining -= cellsUsed;
        maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
        if (cellsUsed == 1)
            smallestItemsAt |= (1 << i);
    }
    // When we have overflow and a single expanded (text) item, we want to try centering it
    // visually in the available space even though overflow consumes some of it.
    final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
    // Divide space for remaining cells if we have items that can expand.
    // Try distributing whole leftover cells to smaller items first.
    boolean needsExpansion = false;
    while (expandableItemCount > 0 && cellsRemaining > 0) {
        int minCells = Integer.MAX_VALUE;
        // Bit locations are indices of relevant child views
        long minCellsAt = 0;
        int minCellsItemCount = 0;
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            // Don't try to expand items that shouldn't.
            if (!lp.expandable)
                continue;
            // Mark indices of children that can receive an extra cell.
            if (lp.cellsUsed < minCells) {
                minCells = lp.cellsUsed;
                minCellsAt = 1 << i;
                minCellsItemCount = 1;
            } else if (lp.cellsUsed == minCells) {
                minCellsAt |= 1 << i;
                minCellsItemCount++;
            }
        }
        // Items that get expanded will always be in the set of smallest items when we're done.
        smallestItemsAt |= minCellsAt;
        // Couldn't expand anything evenly. Stop.
        if (minCellsItemCount > cellsRemaining)
            break;
        // We have enough cells, all minimum size items will be incremented.
        minCells++;
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if ((minCellsAt & (1 << i)) == 0) {
                // If this item is already at our small item count, mark it for later.
                if (lp.cellsUsed == minCells)
                    smallestItemsAt |= 1 << i;
                continue;
            }
            if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
                // Add padding to this item such that it centers.
                child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
            }
            lp.cellsUsed++;
            lp.expanded = true;
            cellsRemaining--;
        }
        needsExpansion = true;
    }
    // Divide any space left that wouldn't divide along cell boundaries
    // evenly among the smallest items
    final boolean singleItem = !hasOverflow && visibleItemCount == 1;
    if (cellsRemaining > 0 && smallestItemsAt != 0 && (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
        float expandCount = Long.bitCount(smallestItemsAt);
        if (!singleItem) {
            // The items at the far edges may only expand by half in order to pin to either side.
            if ((smallestItemsAt & 1) != 0) {
                LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
                if (!lp.preventEdgeOffset)
                    expandCount -= 0.5f;
            }
            if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
                LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
                if (!lp.preventEdgeOffset)
                    expandCount -= 0.5f;
            }
        }
        final int extraPixels = expandCount > 0 ? (int) (cellsRemaining * cellSize / expandCount) : 0;
        for (int i = 0; i < childCount; i++) {
            if ((smallestItemsAt & (1 << i)) == 0)
                continue;
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (child instanceof ActionMenuItemView) {
                // If this is one of our views, expand and measure at the larger size.
                lp.extraPixels = extraPixels;
                lp.expanded = true;
                if (i == 0 && !lp.preventEdgeOffset) {
                    // First item gets part of its new padding pushed out of sight.
                    // The last item will get this implicitly from layout.
                    lp.leftMargin = -extraPixels / 2;
                }
                needsExpansion = true;
            } else if (lp.isOverflowButton) {
                lp.extraPixels = extraPixels;
                lp.expanded = true;
                lp.rightMargin = -extraPixels / 2;
                needsExpansion = true;
            } else {
                // against the edges.
                if (i != 0) {
                    lp.leftMargin = extraPixels / 2;
                }
                if (i != childCount - 1) {
                    lp.rightMargin = extraPixels / 2;
                }
            }
        }
        cellsRemaining = 0;
    }
    // Remeasure any items that have had extra space allocated to them.
    if (needsExpansion) {
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (!lp.expanded)
                continue;
            final int width = lp.cellsUsed * cellSize + lp.extraPixels;
            child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), itemHeightSpec);
        }
    }
    if (heightMode != MeasureSpec.EXACTLY) {
        heightSize = maxChildHeight;
    }
    setMeasuredDimension(widthSize, heightSize);
}
Also used : MenuView(com.android.internal.view.menu.MenuView) ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView) View(android.view.View) ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView)

Example 3 with ActionMenuItemView

use of com.android.internal.view.menu.ActionMenuItemView in project android_frameworks_base by ResurrectionRemix.

the class ActionMenuView method measureChildForCells.

/**
     * Measure a child view to fit within cell-based formatting. The child's width
     * will be measured to a whole multiple of cellSize.
     *
     * <p>Sets the expandable and cellsUsed fields of LayoutParams.
     *
     * @param child Child to measure
     * @param cellSize Size of one cell
     * @param cellsRemaining Number of cells remaining that this view can expand to fill
     * @param parentHeightMeasureSpec MeasureSpec used by the parent view
     * @param parentHeightPadding Padding present in the parent view
     * @return Number of cells this child was measured to occupy
     */
static int measureChildForCells(View child, int cellSize, int cellsRemaining, int parentHeightMeasureSpec, int parentHeightPadding) {
    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) - parentHeightPadding;
    final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
    final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
    final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? (ActionMenuItemView) child : null;
    final boolean hasText = itemView != null && itemView.hasText();
    int cellsUsed = 0;
    if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) {
        final int childWidthSpec = MeasureSpec.makeMeasureSpec(cellSize * cellsRemaining, MeasureSpec.AT_MOST);
        child.measure(childWidthSpec, childHeightSpec);
        final int measuredWidth = child.getMeasuredWidth();
        cellsUsed = measuredWidth / cellSize;
        if (measuredWidth % cellSize != 0)
            cellsUsed++;
        if (hasText && cellsUsed < 2)
            cellsUsed = 2;
    }
    final boolean expandable = !lp.isOverflowButton && hasText;
    lp.expandable = expandable;
    lp.cellsUsed = cellsUsed;
    final int targetWidth = cellsUsed * cellSize;
    child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), childHeightSpec);
    return cellsUsed;
}
Also used : ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView)

Example 4 with ActionMenuItemView

use of com.android.internal.view.menu.ActionMenuItemView in project android_frameworks_base by DirtyUnicorns.

the class ActionMenuView method onMeasureExactFormat.

private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
    // We already know the width mode is EXACTLY if we're here.
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    final int widthPadding = getPaddingLeft() + getPaddingRight();
    final int heightPadding = getPaddingTop() + getPaddingBottom();
    final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding, ViewGroup.LayoutParams.WRAP_CONTENT);
    widthSize -= widthPadding;
    // Divide the view into cells.
    final int cellCount = widthSize / mMinCellSize;
    final int cellSizeRemaining = widthSize % mMinCellSize;
    if (cellCount == 0) {
        // Give up, nothing fits.
        setMeasuredDimension(widthSize, 0);
        return;
    }
    final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
    int cellsRemaining = cellCount;
    int maxChildHeight = 0;
    int maxCellsUsed = 0;
    int expandableItemCount = 0;
    int visibleItemCount = 0;
    boolean hasOverflow = false;
    // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
    long smallestItemsAt = 0;
    final int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() == GONE)
            continue;
        final boolean isGeneratedItem = child instanceof ActionMenuItemView;
        visibleItemCount++;
        if (isGeneratedItem) {
            // Reset padding for generated menu item views; it may change below
            // and views are recycled.
            child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
        }
        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
        lp.expanded = false;
        lp.extraPixels = 0;
        lp.cellsUsed = 0;
        lp.expandable = false;
        lp.leftMargin = 0;
        lp.rightMargin = 0;
        lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
        // Overflow always gets 1 cell. No more, no less.
        final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
        final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, itemHeightSpec, heightPadding);
        maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
        if (lp.expandable)
            expandableItemCount++;
        if (lp.isOverflowButton)
            hasOverflow = true;
        cellsRemaining -= cellsUsed;
        maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
        if (cellsUsed == 1)
            smallestItemsAt |= (1 << i);
    }
    // When we have overflow and a single expanded (text) item, we want to try centering it
    // visually in the available space even though overflow consumes some of it.
    final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
    // Divide space for remaining cells if we have items that can expand.
    // Try distributing whole leftover cells to smaller items first.
    boolean needsExpansion = false;
    while (expandableItemCount > 0 && cellsRemaining > 0) {
        int minCells = Integer.MAX_VALUE;
        // Bit locations are indices of relevant child views
        long minCellsAt = 0;
        int minCellsItemCount = 0;
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            // Don't try to expand items that shouldn't.
            if (!lp.expandable)
                continue;
            // Mark indices of children that can receive an extra cell.
            if (lp.cellsUsed < minCells) {
                minCells = lp.cellsUsed;
                minCellsAt = 1 << i;
                minCellsItemCount = 1;
            } else if (lp.cellsUsed == minCells) {
                minCellsAt |= 1 << i;
                minCellsItemCount++;
            }
        }
        // Items that get expanded will always be in the set of smallest items when we're done.
        smallestItemsAt |= minCellsAt;
        // Couldn't expand anything evenly. Stop.
        if (minCellsItemCount > cellsRemaining)
            break;
        // We have enough cells, all minimum size items will be incremented.
        minCells++;
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if ((minCellsAt & (1 << i)) == 0) {
                // If this item is already at our small item count, mark it for later.
                if (lp.cellsUsed == minCells)
                    smallestItemsAt |= 1 << i;
                continue;
            }
            if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
                // Add padding to this item such that it centers.
                child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
            }
            lp.cellsUsed++;
            lp.expanded = true;
            cellsRemaining--;
        }
        needsExpansion = true;
    }
    // Divide any space left that wouldn't divide along cell boundaries
    // evenly among the smallest items
    final boolean singleItem = !hasOverflow && visibleItemCount == 1;
    if (cellsRemaining > 0 && smallestItemsAt != 0 && (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
        float expandCount = Long.bitCount(smallestItemsAt);
        if (!singleItem) {
            // The items at the far edges may only expand by half in order to pin to either side.
            if ((smallestItemsAt & 1) != 0) {
                LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
                if (!lp.preventEdgeOffset)
                    expandCount -= 0.5f;
            }
            if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
                LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
                if (!lp.preventEdgeOffset)
                    expandCount -= 0.5f;
            }
        }
        final int extraPixels = expandCount > 0 ? (int) (cellsRemaining * cellSize / expandCount) : 0;
        for (int i = 0; i < childCount; i++) {
            if ((smallestItemsAt & (1 << i)) == 0)
                continue;
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (child instanceof ActionMenuItemView) {
                // If this is one of our views, expand and measure at the larger size.
                lp.extraPixels = extraPixels;
                lp.expanded = true;
                if (i == 0 && !lp.preventEdgeOffset) {
                    // First item gets part of its new padding pushed out of sight.
                    // The last item will get this implicitly from layout.
                    lp.leftMargin = -extraPixels / 2;
                }
                needsExpansion = true;
            } else if (lp.isOverflowButton) {
                lp.extraPixels = extraPixels;
                lp.expanded = true;
                lp.rightMargin = -extraPixels / 2;
                needsExpansion = true;
            } else {
                // against the edges.
                if (i != 0) {
                    lp.leftMargin = extraPixels / 2;
                }
                if (i != childCount - 1) {
                    lp.rightMargin = extraPixels / 2;
                }
            }
        }
        cellsRemaining = 0;
    }
    // Remeasure any items that have had extra space allocated to them.
    if (needsExpansion) {
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            if (!lp.expanded)
                continue;
            final int width = lp.cellsUsed * cellSize + lp.extraPixels;
            child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), itemHeightSpec);
        }
    }
    if (heightMode != MeasureSpec.EXACTLY) {
        heightSize = maxChildHeight;
    }
    setMeasuredDimension(widthSize, heightSize);
}
Also used : MenuView(com.android.internal.view.menu.MenuView) ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView) View(android.view.View) ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView)

Example 5 with ActionMenuItemView

use of com.android.internal.view.menu.ActionMenuItemView in project android_frameworks_base by DirtyUnicorns.

the class ActionMenuPresenter method bindItemView.

@Override
public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
    itemView.initialize(item, 0);
    final ActionMenuView menuView = (ActionMenuView) mMenuView;
    final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
    actionItemView.setItemInvoker(menuView);
    if (mPopupCallback == null) {
        mPopupCallback = new ActionMenuPopupCallback();
    }
    actionItemView.setPopupCallback(mPopupCallback);
}
Also used : ActionMenuItemView(com.android.internal.view.menu.ActionMenuItemView)

Aggregations

ActionMenuItemView (com.android.internal.view.menu.ActionMenuItemView)20 Nullable (android.annotation.Nullable)5 View (android.view.View)5 BridgeMenuItemImpl (com.android.internal.view.menu.BridgeMenuItemImpl)5 IconMenuItemView (com.android.internal.view.menu.IconMenuItemView)5 ListMenuItemView (com.android.internal.view.menu.ListMenuItemView)5 MenuItemImpl (com.android.internal.view.menu.MenuItemImpl)5 MenuView (com.android.internal.view.menu.MenuView)5 BridgeContext (com.android.layoutlib.bridge.android.BridgeContext)5