/** * Places a single view on the current row, and updates the view's layout parameters to remember * its position. mStart, mEnd, and mBottom are updated to reflect the space taken by the view. */ private void placeChild(View child, int gravity) { LayoutParams lp = (LayoutParams) child.getLayoutParams(); int availableWidth = Math.max(0, mEnd - mStart - lp.startMargin - lp.endMargin); if (child.getMeasuredWidth() > availableWidth || gravity == Gravity.FILL_HORIZONTAL) { measureChildWithFixedWidth(child, availableWidth); } if (gravity == Gravity.START || gravity == Gravity.FILL_HORIZONTAL) { lp.start = mStart + lp.startMargin; mStart = lp.start + child.getMeasuredWidth() + lp.endMargin; } else { // gravity == Gravity.END lp.start = mEnd - lp.endMargin - child.getMeasuredWidth(); mEnd = lp.start - lp.startMargin; } lp.top = mTop + lp.topMargin; mBottom = Math.max(mBottom, lp.top + child.getMeasuredHeight() + lp.bottomMargin); }
/** * Assigns positions to all of the views in the infobar. The icon, text, and close button are * placed on the main row. The custom content and finally the buttons are placed on the main row * if they fit. Otherwise, they go on their own rows. */ private void placeGroups() { startRow(); placeChild(mCloseButton, Gravity.END); placeGroup(mMainGroup); int customGroupWidth = 0; if (mCustomGroup != null) { updateCustomGroupForRow(ROW_MAIN); customGroupWidth = getWidthWithMargins(mCustomGroup); } int buttonGroupWidth = 0; if (mButtonGroup != null) { updateButtonGroupForRow(ROW_MAIN); buttonGroupWidth = getWidthWithMargins(mButtonGroup); } boolean customGroupOnMainRow = customGroupWidth <= availableWidth(); boolean buttonGroupOnMainRow = customGroupWidth + buttonGroupWidth <= availableWidth(); if (mCustomGroup != null) { if (customGroupOnMainRow) { mCustomGroup.gravity = (mButtonGroup != null && buttonGroupOnMainRow) ? Gravity.START : Gravity.END; } else { startRow(); updateCustomGroupForRow(ROW_OTHER); } placeGroup(mCustomGroup); } if (mButtonGroup != null) { if (!buttonGroupOnMainRow) { startRow(); updateButtonGroupForRow(ROW_OTHER); // If the infobar consists of just a main row and a buttons row, the buttons must be // at least 32dp below the bottom of the message text. if (mCustomGroup == null && mMessageTextView != null) { LayoutParams lp = (LayoutParams) mMessageTextView.getLayoutParams(); int messageBottom = lp.top + mMessageTextView.getMeasuredHeight(); mTop = Math.max(mTop, messageBottom + 2 * mMargin); } } placeGroup(mButtonGroup); if (mCustomButton != null && !buttonGroupOnMainRow) { // The custom button is start-aligned with the message view (unless that causes it // to overlap the primary button). LayoutParams primaryButtonLP = (LayoutParams) mPrimaryButton.getLayoutParams(); LayoutParams customButtonLP = (LayoutParams) mCustomButton.getLayoutParams(); LayoutParams messageLP = (LayoutParams) mMessageView.getLayoutParams(); if (customButtonLP.start >= messageLP.start) { customButtonLP.start = messageLP.start; } else { customButtonLP.start = mMargin; } if (!mButtonGroup.isStacked) { // Center the custom button vertically relative to the primary button. customButtonLP.top = primaryButtonLP.top + (mPrimaryButton.getMeasuredHeight() - mCustomButton.getMeasuredHeight()) / 2; } } } startRow(); // If everything fits on a single row, center everything vertically. if (buttonGroupOnMainRow) { int layoutHeight = mBottom; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); int extraSpace = layoutHeight - child.getMeasuredHeight(); LayoutParams lp = (LayoutParams) child.getLayoutParams(); lp.top = extraSpace / 2; } } }