Merge "Support min/max height for FloatingToolbar overflow." into mnc-dev

This commit is contained in:
Abodunrinwa Toki
2015-05-18 16:56:53 +00:00
committed by Android (Google) Code Review
3 changed files with 90 additions and 61 deletions

View File

@@ -79,7 +79,6 @@ public final class FloatingToolbar {
private final FloatingToolbarPopup mPopup;
private final Rect mContentRect = new Rect();
private final Point mCoordinates = new Point();
private Menu mMenu;
private List<CharSequence> mShowingTitles = new ArrayList<CharSequence>();
@@ -87,7 +86,6 @@ public final class FloatingToolbar {
private int mSuggestedWidth;
private boolean mWidthChanged = true;
private int mOverflowDirection;
/**
* Initializes a floating toolbar.
@@ -157,11 +155,9 @@ public final class FloatingToolbar {
mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
mShowingTitles = getMenuItemTitles(menuItems);
}
refreshCoordinates();
mPopup.setOverflowDirection(mOverflowDirection);
mPopup.updateCoordinates(mCoordinates.x, mCoordinates.y);
mPopup.updateCoordinates(mContentRect);
if (!mPopup.isShowing()) {
mPopup.show(mCoordinates.x, mCoordinates.y);
mPopup.show(mContentRect);
}
mWidthChanged = false;
return this;
@@ -208,25 +204,6 @@ public final class FloatingToolbar {
return mPopup.isHidden();
}
/**
* Refreshes {@link #mCoordinates} with values based on {@link #mContentRect}.
*/
private void refreshCoordinates() {
int x = mContentRect.centerX() - mPopup.getWidth() / 2;
int y;
if (mContentRect.top > mPopup.getHeight()) {
y = mContentRect.top - mPopup.getHeight();
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP;
} else if (mContentRect.top > mPopup.getToolbarHeightWithVerticalMargin()) {
y = mContentRect.top - mPopup.getToolbarHeightWithVerticalMargin();
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
} else {
y = mContentRect.bottom;
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
}
mCoordinates.set(x, y);
}
/**
* Returns true if this floating toolbar is currently showing the specified menu items.
*/
@@ -345,6 +322,8 @@ public final class FloatingToolbar {
}
};
private final Point mCoords = new Point();
private final Region mTouchableRegion = new Region();
private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
new ViewTreeObserver.OnComputeInternalInsetsListener() {
@@ -404,6 +383,8 @@ public final class FloatingToolbar {
*/
public void layoutMenuItems(List<MenuItem> menuItems,
MenuItem.OnMenuItemClickListener menuItemClickListener, int suggestedWidth) {
Preconditions.checkNotNull(menuItems);
mContentContainer.removeAllViews();
if (mMainPanel == null) {
mMainPanel = new FloatingToolbarMainPanel(mParent.getContext(), mOpenOverflow);
@@ -426,7 +407,9 @@ public final class FloatingToolbar {
* Shows this popup at the specified coordinates.
* The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
*/
public void show(int x, int y) {
public void show(Rect contentRect) {
Preconditions.checkNotNull(contentRect);
if (isShowing()) {
return;
}
@@ -435,6 +418,7 @@ public final class FloatingToolbar {
mDismissed = false;
cancelDismissAndHideAnimations();
cancelOverflowAnimations();
// Make sure a panel is set as the content.
if (mContentContainer.getChildCount() == 0) {
setMainPanelAsContent();
@@ -442,8 +426,10 @@ public final class FloatingToolbar {
// The "show" animation will make this visible.
mContentContainer.setAlpha(0);
}
updateOverflowHeight(contentRect.top - (mMarginVertical * 2));
refreshCoordinatesAndOverflowDirection(contentRect);
preparePopupContent();
mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y);
mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y);
setTouchableSurfaceInsetsComputer();
runShowAnimation();
}
@@ -496,27 +482,17 @@ public final class FloatingToolbar {
* The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
* This is a no-op if this popup is not showing.
*/
public void updateCoordinates(int x, int y) {
public void updateCoordinates(Rect contentRect) {
Preconditions.checkNotNull(contentRect);
if (!isShowing() || !mPopupWindow.isShowing()) {
return;
}
cancelOverflowAnimations();
refreshCoordinatesAndOverflowDirection(contentRect);
preparePopupContent();
mPopupWindow.update(x, y, getWidth(), getHeight());
}
/**
* Sets the direction in which the overflow will open. i.e. up or down.
*
* @param overflowDirection Either {@link #OVERFLOW_DIRECTION_UP}
* or {@link #OVERFLOW_DIRECTION_DOWN}.
*/
public void setOverflowDirection(int overflowDirection) {
mOverflowDirection = overflowDirection;
if (mOverflowPanel != null) {
mOverflowPanel.setOverflowDirection(mOverflowDirection);
}
mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight());
}
/**
@@ -540,7 +516,26 @@ public final class FloatingToolbar {
return mContentContainer.getContext();
}
int getToolbarHeightWithVerticalMargin() {
private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
int x = contentRect.centerX() - getWidth() / 2;
int y;
if (contentRect.top > getHeight()) {
y = contentRect.top - getHeight();
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP;
} else if (contentRect.top > getToolbarHeightWithVerticalMargin()) {
y = contentRect.top - getToolbarHeightWithVerticalMargin();
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
} else {
y = contentRect.bottom;
mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
}
mCoords.set(x, y);
if (mOverflowPanel != null) {
mOverflowPanel.setOverflowDirection(mOverflowDirection);
}
}
private int getToolbarHeightWithVerticalMargin() {
return getEstimatedToolbarHeight(mParent.getContext()) + mMarginVertical * 2;
}
@@ -693,16 +688,24 @@ public final class FloatingToolbar {
}
// Reset position.
if (mMainPanel != null
&& mContentContainer.getChildAt(0) == mMainPanel.getView()) {
if (isMainPanelContent()) {
positionMainPanel();
}
if (mOverflowPanel != null
&& mContentContainer.getChildAt(0) == mOverflowPanel.getView()) {
if (isOverflowPanelContent()) {
positionOverflowPanel();
}
}
private boolean isMainPanelContent() {
return mMainPanel != null
&& mContentContainer.getChildAt(0) == mMainPanel.getView();
}
private boolean isOverflowPanelContent() {
return mOverflowPanel != null
&& mContentContainer.getChildAt(0) == mOverflowPanel.getView();
}
/**
* Sets the current content to be the main view panel.
*/
@@ -765,6 +768,25 @@ public final class FloatingToolbar {
setContentAreaAsTouchableSurface();
}
private void updateOverflowHeight(int height) {
if (mOverflowPanel != null) {
mOverflowPanel.setSuggestedHeight(height);
// Re-measure the popup and it's contents.
boolean mainPanelContent = isMainPanelContent();
boolean overflowPanelContent = isOverflowPanelContent();
mContentContainer.removeAllViews(); // required to update popup size.
updatePopupSize();
// Reset the appropriate content.
if (mainPanelContent) {
setMainPanelAsContent();
}
if (overflowPanelContent) {
setOverflowPanelAsContent();
}
}
}
private void updatePopupSize() {
int width = 0;
int height = 0;
@@ -864,6 +886,8 @@ public final class FloatingToolbar {
* @return The menu items that are not included in this main panel.
*/
public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int suggestedWidth) {
Preconditions.checkNotNull(menuItems);
final int toolbarWidth = getAdjustedToolbarWidth(mContext, suggestedWidth)
// Reserve space for the "open overflow" button.
- getEstimatedOpenOverflowButtonWidth(mContext);
@@ -972,6 +996,7 @@ public final class FloatingToolbar {
private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener;
private int mOverflowWidth = 0;
private int mSuggestedHeight;
/**
* Initializes a floating toolbar popup overflow view panel.
@@ -981,6 +1006,7 @@ public final class FloatingToolbar {
*/
public FloatingToolbarOverflowPanel(Context context, Runnable closeOverflow) {
mCloseOverflow = Preconditions.checkNotNull(closeOverflow);
mSuggestedHeight = getScreenHeight(context);
mContentView = new LinearLayout(context);
mContentView.setOrientation(LinearLayout.VERTICAL);
@@ -1043,6 +1069,11 @@ public final class FloatingToolbar {
mContentView.addView(mBackButtonContainer, index);
}
public void setSuggestedHeight(int height) {
mSuggestedHeight = height;
setListViewHeight();
}
/**
* Returns the content view of the overflow.
*/
@@ -1074,9 +1105,17 @@ public final class FloatingToolbar {
int itemHeight = getEstimatedToolbarHeight(mContentView.getContext());
int height = mListView.getAdapter().getCount() * itemHeight;
int maxHeight = mContentView.getContext().getResources().
getDimensionPixelSize(R.dimen.floating_toolbar_maximum_overflow_height);
int minHeight = mContentView.getContext().getResources().
getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height);
int availableHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight)
- itemHeight; // reserve space for the back button.
ViewGroup.LayoutParams params = mListView.getLayoutParams();
params.height = Math.min(height, maxHeight);
if (availableHeight >= minHeight) {
params.height = Math.min(Math.min(availableHeight, maxHeight), height);
} else {
params.height = Math.min(maxHeight, height);
}
mListView.setLayoutParams(params);
}
@@ -1271,16 +1310,4 @@ public final class FloatingToolbar {
private static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* Returns value, restricted to the range min->max (inclusive).
* If maximum is less than minimum, the result is undefined.
*
* @param value The value to clamp.
* @param minimum The minimum value in the range.
* @param maximum The maximum value in the range. Must not be less than minimum.
*/
private static int clamp(int value, int minimum, int maximum) {
return Math.max(minimum, Math.min(value, maximum));
}
}

View File

@@ -392,7 +392,8 @@
<dimen name="floating_toolbar_text_size">14sp</dimen>
<dimen name="floating_toolbar_menu_button_minimum_width">48dp</dimen>
<dimen name="floating_toolbar_preferred_width">328dp</dimen>
<dimen name="floating_toolbar_minimum_overflow_height">144dp</dimen>
<dimen name="floating_toolbar_minimum_overflow_height">96dp</dimen>
<dimen name="floating_toolbar_maximum_overflow_height">192dp</dimen>
<dimen name="floating_toolbar_horizontal_margin">16dp</dimen>
<dimen name="floating_toolbar_vertical_margin">8dp</dimen>

View File

@@ -2256,6 +2256,7 @@
<java-symbol type="dimen" name="floating_toolbar_menu_button_minimum_width" />
<java-symbol type="dimen" name="floating_toolbar_preferred_width" />
<java-symbol type="dimen" name="floating_toolbar_minimum_overflow_height" />
<java-symbol type="dimen" name="floating_toolbar_maximum_overflow_height" />
<java-symbol type="dimen" name="floating_toolbar_horizontal_margin" />
<java-symbol type="dimen" name="floating_toolbar_vertical_margin" />