Commit fb839cf4 authored by Gang Wu's avatar Gang Wu Committed by Commit Bot

Calculate App Menu height programmatically

This CL add an new API to CustomViewBinder#getPixelHeight which allow
each custom view can return their height individually. The height is
based on the layout file related to the custom view.

This CL also add padding before and after the divider line, and render
test for it.

Bug:1114611

Change-Id: I5e104dd5cdcdcf4acf20beeab6a682b4d4bba152
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2387542
Commit-Queue: Gang Wu <gangwu@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarSinan Sahin <sinansahin@google.com>
Cr-Commit-Position: refs/heads/master@{#804388}
parent 9fd2ca9e
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
style="@style/AppMenuItem" style="@style/AppMenuItem"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingVertical="@dimen/overflow_menu_divider_line_padding"
android:importantForAccessibility="noHideDescendants" android:importantForAccessibility="noHideDescendants"
android:visibility="visible" android:visibility="visible"
android:focusable="false"> android:focusable="false">
......
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
android:id="@+id/menu_item_text" android:id="@+id/menu_item_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="12dp" android:minHeight="@dimen/overflow_menu_managed_by_min_height"
android:paddingBottom="12dp" android:paddingVertical="12dp"
android:text="@string/managed" android:text="@string/managed"
android:textAppearance="@style/TextAppearance.TextMedium.Secondary" android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
android:singleLine="true" android:singleLine="true"
......
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
style="@style/AppMenuItem" style="@style/AppMenuItem"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="12dp" android:paddingVertical="@dimen/overflow_menu_update_padding"
android:paddingBottom="12dp"
android:orientation="horizontal" > android:orientation="horizontal" >
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="@dimen/overflow_menu_update_min_height"
android:layout_weight="1" android:layout_weight="1"
android:layout_gravity="start" android:layout_gravity="start"
android:paddingEnd="9dp" android:paddingEnd="9dp"
...@@ -24,12 +24,14 @@ ...@@ -24,12 +24,14 @@
android:id="@+id/menu_item_text" android:id="@+id/menu_item_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.UpdateMenuItem" /> android:textAppearance="@style/TextAppearance.UpdateMenuItem" />
<TextView <TextView
android:id="@+id/menu_item_summary" android:id="@+id/menu_item_summary"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.TextSmall.Secondary" /> android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
</LinearLayout> </LinearLayout>
......
...@@ -578,4 +578,12 @@ ...@@ -578,4 +578,12 @@
<dimen name="status_indicator_min_height">21dp</dimen> <dimen name="status_indicator_min_height">21dp</dimen>
<dimen name="status_indicator_icon_padding">8dp</dimen> <dimen name="status_indicator_icon_padding">8dp</dimen>
<dimen name="status_indicator_icon_size">12dp</dimen> <dimen name="status_indicator_icon_size">12dp</dimen>
<!-- Overflow Menu Dimensions -->
<dimen name="overflow_menu_divider_line_padding">5dp</dimen>
<!-- top padding(12dp) + icon size(20dp) + bottom padding(12dp) -->
<dimen name="overflow_menu_managed_by_min_height">44dp</dimen>
<dimen name="overflow_menu_update_min_height">40sp</dimen>
<dimen name="overflow_menu_update_padding">12dp</dimen>
</resources> </resources>
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.app.appmenu; package org.chromium.chrome.browser.app.appmenu;
import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
...@@ -44,4 +45,13 @@ class DividerLineMenuItemViewBinder implements CustomViewBinder { ...@@ -44,4 +45,13 @@ class DividerLineMenuItemViewBinder implements CustomViewBinder {
public boolean supportsEnterAnimation(int id) { public boolean supportsEnterAnimation(int id) {
return true; return true;
} }
@Override
public int getPixelHeight(Context context) {
int dividerLineHeight =
context.getResources().getDimensionPixelSize(R.dimen.divider_height);
int paddingSize = context.getResources().getDimensionPixelSize(
R.dimen.overflow_menu_divider_line_padding);
return dividerLineHeight + paddingSize * 2 /* top padding and bottom padding */;
}
} }
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.app.appmenu; package org.chromium.chrome.browser.app.appmenu;
import android.content.Context;
import android.content.res.TypedArray;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
...@@ -63,6 +65,13 @@ class IncognitoMenuItemViewBinder implements CustomViewBinder { ...@@ -63,6 +65,13 @@ class IncognitoMenuItemViewBinder implements CustomViewBinder {
return true; return true;
} }
@Override
public int getPixelHeight(Context context) {
TypedArray a = context.obtainStyledAttributes(
new int[] {android.R.attr.listPreferredItemHeightSmall});
return a.getDimensionPixelSize(0, 0);
}
private static class IncognitoMenuItemViewHolder { private static class IncognitoMenuItemViewHolder {
public TextViewWithCompoundDrawables title; public TextViewWithCompoundDrawables title;
public ChromeImageView image; public ChromeImageView image;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.app.appmenu; package org.chromium.chrome.browser.app.appmenu;
import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
...@@ -46,4 +47,14 @@ class ManagedByMenuItemViewBinder implements CustomViewBinder { ...@@ -46,4 +47,14 @@ class ManagedByMenuItemViewBinder implements CustomViewBinder {
public boolean supportsEnterAnimation(int id) { public boolean supportsEnterAnimation(int id) {
return true; return true;
} }
@Override
public int getPixelHeight(Context context) {
// TODO(crbug.com/1124607): Update this menu item for new app menu.
int dividerLineHeight =
context.getResources().getDimensionPixelSize(R.dimen.divider_height);
int itemSize = context.getResources().getDimensionPixelSize(
R.dimen.overflow_menu_managed_by_min_height);
return dividerLineHeight + itemSize;
}
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.app.appmenu; package org.chromium.chrome.browser.app.appmenu;
import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -14,6 +15,7 @@ import android.view.ViewGroup; ...@@ -14,6 +15,7 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.graphics.drawable.DrawableCompat;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
...@@ -41,7 +43,6 @@ class UpdateMenuItemViewBinder implements CustomViewBinder { ...@@ -41,7 +43,6 @@ class UpdateMenuItemViewBinder implements CustomViewBinder {
public View getView( public View getView(
MenuItem item, View convertView, ViewGroup parent, LayoutInflater inflater) { MenuItem item, View convertView, ViewGroup parent, LayoutInflater inflater) {
assert item.getItemId() == R.id.update_menu_id; assert item.getItemId() == R.id.update_menu_id;
UpdateMenuItemViewHolder holder; UpdateMenuItemViewHolder holder;
if (convertView == null || !(convertView.getTag() instanceof UpdateMenuItemViewHolder)) { if (convertView == null || !(convertView.getTag() instanceof UpdateMenuItemViewHolder)) {
holder = new UpdateMenuItemViewHolder(); holder = new UpdateMenuItemViewHolder();
...@@ -100,4 +101,16 @@ class UpdateMenuItemViewBinder implements CustomViewBinder { ...@@ -100,4 +101,16 @@ class UpdateMenuItemViewBinder implements CustomViewBinder {
public ImageView image; public ImageView image;
public TextView summary; public TextView summary;
} }
@Override
public int getPixelHeight(Context context) {
int textSize = context.getResources().getDimensionPixelSize(
R.dimen.overflow_menu_update_min_height);
int paddingSize =
context.getResources().getDimensionPixelSize(R.dimen.overflow_menu_update_padding);
int iconSize = AppCompatResources.getDrawable(context, R.drawable.menu_update)
.getIntrinsicHeight();
return Math.max(textSize, iconSize) + paddingSize * 2 /* top padding and bottom padding */;
}
} }
...@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.app.appmenu; ...@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.app.appmenu;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
...@@ -346,6 +347,28 @@ public class TabbedAppMenuTest { ...@@ -346,6 +347,28 @@ public class TabbedAppMenuTest {
mRenderTestRule.render(getListView().getChildAt(0), "icon_row_share_enabled"); mRenderTestRule.render(getListView().getChildAt(0), "icon_row_share_enabled");
} }
@Test
@SmallTest
@Feature({"Browser", "Main", "RenderTest"})
@EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_REGROUP})
public void testDividerLineMenuItem() throws IOException {
Menu menu = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator());
int firstDividerLineIndex = -1;
boolean foundDividerLine = false;
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (item.isVisible()) {
firstDividerLineIndex++;
}
if (item.getItemId() == R.id.divider_line_id) {
foundDividerLine = true;
break;
}
}
Assert.assertTrue("No divider line found.", foundDividerLine);
mRenderTestRule.render(getListView().getChildAt(firstDividerLineIndex), "divider_line");
}
private void showAppMenuAndAssertMenuShown() { private void showAppMenuAndAssertMenuShown() {
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT,
() ()
......
...@@ -235,16 +235,13 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -235,16 +235,13 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
mIsByPermanentButton = isByPermanentButton; mIsByPermanentButton = isByPermanentButton;
// Extract visible items from the Menu. // Extract visible items from the Menu.
int numItems = mMenu.size();
int numGroupDivider = 0;
List<MenuItem> menuItems = new ArrayList<MenuItem>(); List<MenuItem> menuItems = new ArrayList<MenuItem>();
for (int i = 0; i < numItems; ++i) { List<Integer> heightList = new ArrayList<Integer>();
for (int i = 0; i < mMenu.size(); ++i) {
MenuItem item = mMenu.getItem(i); MenuItem item = mMenu.getItem(i);
if (item.isVisible()) { if (item.isVisible()) {
menuItems.add(item); menuItems.add(item);
if (item.getItemId() == groupDividerResourceId) { heightList.add(getMenuItemHeight(item, context, customViewBinders));
numGroupDivider++;
}
} }
} }
...@@ -277,8 +274,8 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -277,8 +274,8 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
// See crbug.com/761726. // See crbug.com/761726.
mListView.setAdapter(mAdapter); mListView.setAdapter(mAdapter);
int popupHeight = setMenuHeight(menuItems.size() - numGroupDivider, visibleDisplayFrame, int popupHeight = setMenuHeight(menuItems, heightList, visibleDisplayFrame, screenHeight,
screenHeight, sizingPadding, footerHeight, headerHeight, anchorView); sizingPadding, footerHeight, headerHeight, anchorView, groupDividerResourceId);
int[] popupPosition = getPopupPosition(mTempLocation, mIsByPermanentButton, int[] popupPosition = getPopupPosition(mTempLocation, mIsByPermanentButton,
mNegativeSoftwareVerticalOffset, mNegativeVerticalOffsetNotTopAnchored, mNegativeSoftwareVerticalOffset, mNegativeVerticalOffsetNotTopAnchored,
mCurrentScreenRotation, visibleDisplayFrame, sizingPadding, anchorView, popupWidth, mCurrentScreenRotation, visibleDisplayFrame, sizingPadding, anchorView, popupWidth,
...@@ -469,11 +466,9 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -469,11 +466,9 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
if (mAdapter != null) mAdapter.notifyDataSetChanged(); if (mAdapter != null) mAdapter.notifyDataSetChanged();
} }
// TODO(crbug.com/1114611): Calculate app menu height by each items height since custom menu private int setMenuHeight(List<MenuItem> menuItems, List<Integer> heightList,
// item may have different height than |mItemRowHeight|. Rect appDimensions, int screenHeight, Rect padding, int footerHeight, int headerHeight,
private int setMenuHeight(int numMenuItems, Rect appDimensions, int screenHeight, Rect padding, View anchorView, @IdRes int groupDividerResourceId) {
int footerHeight, int headerHeight, View anchorView) {
int menuHeight;
anchorView.getLocationOnScreen(mTempLocation); anchorView.getLocationOnScreen(mTempLocation);
int anchorViewY = mTempLocation[1] - appDimensions.top; int anchorViewY = mTempLocation[1] - appDimensions.top;
...@@ -489,27 +484,51 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -489,27 +484,51 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
availableScreenSpace -= (padding.bottom + footerHeight + headerHeight); availableScreenSpace -= (padding.bottom + footerHeight + headerHeight);
if (mIsByPermanentButton) availableScreenSpace -= padding.top; if (mIsByPermanentButton) availableScreenSpace -= padding.top;
int numCanFit = availableScreenSpace / (mItemRowHeight + mItemDividerHeight); int menuHeight = calculateHeightForItems(
menuItems, heightList, groupDividerResourceId, availableScreenSpace);
menuHeight += footerHeight + headerHeight + padding.top + padding.bottom;
mPopup.setHeight(menuHeight);
return menuHeight;
}
@VisibleForTesting
int calculateHeightForItems(List<MenuItem> menuItems, List<Integer> heightList,
@IdRes int groupDividerResourceId, int availableScreenSpace) {
int spaceForFullItems = 0;
for (int i = 0; i < heightList.size(); i++) {
spaceForFullItems += heightList.get(i);
}
int menuHeight;
// Fade out the last item if we cannot fit all items. // Fade out the last item if we cannot fit all items.
if (numCanFit < numMenuItems) { if (availableScreenSpace < spaceForFullItems) {
int spaceForFullItems = numCanFit * (mItemRowHeight + mItemDividerHeight); int spaceForItems = 0;
spaceForFullItems += footerHeight + headerHeight; int lastItem = 0;
for (; lastItem < heightList.size(); lastItem++) {
int spaceForPartialItem = (int) (LAST_ITEM_SHOW_FRACTION * mItemRowHeight); if (spaceForItems + heightList.get(lastItem) > availableScreenSpace) {
// Determine which item needs hiding. break;
if (spaceForFullItems + spaceForPartialItem < availableScreenSpace) { }
menuHeight = spaceForFullItems + spaceForPartialItem + padding.top + padding.bottom; spaceForItems += heightList.get(lastItem);
} else { }
menuHeight = spaceForFullItems - mItemRowHeight + spaceForPartialItem + padding.top assert lastItem > 0;
+ padding.bottom;
int spaceForPartialItem = (int) (LAST_ITEM_SHOW_FRACTION * heightList.get(lastItem));
// Determine which item needs hiding. We only show Partial of the last item, if there is
// not enough screen space to partially show the last identified item, then partially
// show the second to last item instead. We also do not show the partial divider line.
assert menuItems.size() == heightList.size();
while (spaceForItems + spaceForPartialItem > availableScreenSpace
|| menuItems.get(lastItem).getItemId() == groupDividerResourceId) {
spaceForItems -= heightList.get(lastItem - 1);
spaceForPartialItem =
(int) (LAST_ITEM_SHOW_FRACTION * heightList.get(lastItem - 1));
lastItem--;
} }
menuHeight = spaceForItems + spaceForPartialItem;
} else { } else {
int spaceForFullItems = numMenuItems * (mItemRowHeight + mItemDividerHeight); menuHeight = spaceForFullItems;
spaceForFullItems += footerHeight + headerHeight;
menuHeight = spaceForFullItems + padding.top + padding.bottom;
} }
mPopup.setHeight(menuHeight);
return menuHeight; return menuHeight;
} }
...@@ -579,4 +598,18 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -579,4 +598,18 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
final long timeToTakeActionMs = SystemClock.elapsedRealtime() - mMenuShownTimeMs; final long timeToTakeActionMs = SystemClock.elapsedRealtime() - mMenuShownTimeMs;
RecordHistogram.recordMediumTimesHistogram(histogramName, timeToTakeActionMs); RecordHistogram.recordMediumTimesHistogram(histogramName, timeToTakeActionMs);
} }
private int getMenuItemHeight(
MenuItem item, Context context, @Nullable List<CustomViewBinder> customViewBinders) {
// Check if |item| is custom type
if (customViewBinders != null) {
for (int i = 0; i < customViewBinders.size(); i++) {
CustomViewBinder binder = customViewBinders.get(i);
if (binder.getItemViewType(item.getItemId()) != CustomViewBinder.NOT_HANDLED) {
return binder.getPixelHeight(context);
}
}
}
return mItemRowHeight;
}
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.ui.appmenu; package org.chromium.chrome.browser.ui.appmenu;
import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
...@@ -551,6 +552,11 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -551,6 +552,11 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
public boolean supportsEnterAnimation(int id) { public boolean supportsEnterAnimation(int id) {
return true; return true;
} }
@Override
public int getPixelHeight(Context context) {
return 0;
}
} }
private static class CustomViewBinderTwo implements CustomViewBinder { private static class CustomViewBinderTwo implements CustomViewBinder {
...@@ -589,5 +595,10 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -589,5 +595,10 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
public boolean supportsEnterAnimation(int id) { public boolean supportsEnterAnimation(int id) {
return false; return false;
} }
@Override
public int getPixelHeight(Context context) {
return 0;
}
} }
} }
...@@ -6,6 +6,8 @@ package org.chromium.chrome.browser.ui.appmenu; ...@@ -6,6 +6,8 @@ package org.chromium.chrome.browser.ui.appmenu;
import android.graphics.Rect; import android.graphics.Rect;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
...@@ -14,6 +16,7 @@ import android.widget.TextView; ...@@ -14,6 +16,7 @@ import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.test.filters.MediumTest; import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
...@@ -37,6 +40,8 @@ import org.chromium.ui.test.util.DummyUiActivity; ...@@ -37,6 +40,8 @@ import org.chromium.ui.test.util.DummyUiActivity;
import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.DummyUiActivityTestCase;
import org.chromium.ui.test.util.UiDisableIf; import org.chromium.ui.test.util.UiDisableIf;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
...@@ -652,6 +657,104 @@ public class AppMenuTest extends DummyUiActivityTestCase { ...@@ -652,6 +657,104 @@ public class AppMenuTest extends DummyUiActivityTestCase {
mDelegate.lastSelectedItemId); mDelegate.lastSelectedItemId);
} }
@Test
@SmallTest
public void testCalculateHeightForItems_enoughSpace() throws Exception {
showMenuAndAssert();
List<MenuItem> menuItems = new ArrayList<MenuItem>();
List<Integer> heightList = new ArrayList<Integer>();
createMenuItem(menuItems, heightList, 0 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 1 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 2 /* id */, 10 /* height */);
int height = mAppMenuHandler.getAppMenu().calculateHeightForItems(menuItems, heightList,
-1 /* groupDividerResourceId */, 35 /* availableScreenSpace */);
Assert.assertEquals(30, height);
}
@Test
@SmallTest
public void testCalculateHeightForItems_notEnoughSpaceForOneItem() throws Exception {
showMenuAndAssert();
List<MenuItem> menuItems = new ArrayList<MenuItem>();
List<Integer> heightList = new ArrayList<Integer>();
createMenuItem(menuItems, heightList, 0 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 1 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 2 /* id */, 10 /* height */);
int height = mAppMenuHandler.getAppMenu().calculateHeightForItems(menuItems, heightList,
-1 /* groupDividerResourceId */, 26 /* availableScreenSpace */);
// The space only can fit the 1st and 2nd items and the partial 3rd item.
Assert.assertEquals(25, height);
}
@Test
@SmallTest
public void testCalculateHeightForItems_notEnoughSpaceForTwoItem() throws Exception {
showMenuAndAssert();
List<MenuItem> menuItems = new ArrayList<MenuItem>();
List<Integer> heightList = new ArrayList<Integer>();
createMenuItem(menuItems, heightList, 0 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 1 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 2 /* id */, 10 /* height */);
int height = mAppMenuHandler.getAppMenu().calculateHeightForItems(menuItems, heightList,
-1 /* groupDividerResourceId */, 24 /* availableScreenSpace */);
// The space only can fit the full 1st item, the full 2nd items and the partial 3rd item.
// But the space for 3rd item is 4, which is not enough to show partial 3rd item(5 =
// LAST_ITEM_SHOW_FRACTION * 10), we show the partial 2nd item instead.
Assert.assertEquals(15, height);
}
@Test
@SmallTest
public void testCalculateHeightForItems_notEnoughSpaceForDivider() throws Exception {
showMenuAndAssert();
List<MenuItem> menuItems = new ArrayList<MenuItem>();
List<Integer> heightList = new ArrayList<Integer>();
createMenuItem(menuItems, heightList, 0 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 1 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 2 /* id */, 10 /* height */);
int height = mAppMenuHandler.getAppMenu().calculateHeightForItems(menuItems, heightList,
1 /* groupDividerResourceId */, 16 /* availableScreenSpace */);
// The space only can fit the 1st and the partial 2nd item. But 2nd item is divider line, so
// we only show the partial 1st item.
Assert.assertEquals(5, height);
}
@Test
@SmallTest
public void testCalculateHeightForItems_notEnoughSpaceForDividerAndItem() throws Exception {
showMenuAndAssert();
List<MenuItem> menuItems = new ArrayList<MenuItem>();
List<Integer> heightList = new ArrayList<Integer>();
createMenuItem(menuItems, heightList, 0 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 1 /* id */, 10 /* height */);
createMenuItem(menuItems, heightList, 2 /* id */, 10 /* height */);
int height = mAppMenuHandler.getAppMenu().calculateHeightForItems(menuItems, heightList,
1 /* groupDividerResourceId */, 24 /* availableScreenSpace */);
// The space only can fit the full 1st item, the full 2nd items and the partial 3rd item.
// But the space for 3rd item is 4, which is not enough to show partial 3rd item(5 =
// LAST_ITEM_SHOW_FRACTION * 10), so we should show the partial 2nd item instead. But 2nd
// item is divider line, so we should partial 1st item instead.
Assert.assertEquals(5, height);
}
private void createMenuItem(
List<MenuItem> menuItems, List<Integer> heightList, int id, int height) {
Menu menu = mAppMenuHandler.getAppMenu().getMenu();
MenuItem item = menu.add(0, id, 0, "test menu item");
menuItems.add(item);
heightList.add(height);
}
private void showMenuAndAssert() throws TimeoutException { private void showMenuAndAssert() throws TimeoutException {
int currentCallCount = mMenuObserver.menuShownCallback.getCallCount(); int currentCallCount = mMenuObserver.menuShownCallback.getCallCount();
TestThreadUtils.runOnUiThreadBlocking( TestThreadUtils.runOnUiThreadBlocking(
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.ui.appmenu; package org.chromium.chrome.browser.ui.appmenu;
import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
...@@ -58,4 +59,14 @@ public interface CustomViewBinder { ...@@ -58,4 +59,14 @@ public interface CustomViewBinder {
* @return True if the standard animation should be applied. * @return True if the standard animation should be applied.
*/ */
boolean supportsEnterAnimation(int id); boolean supportsEnterAnimation(int id);
/**
* Retrieve the pixel height for the custom view. We cannot use View#getHeight() in {{@link
* #getView(MenuItem, View, ViewGroup, LayoutInflater)}} because View#getHeight() will return 0
* before the view is laid out. This method is for calculating popup window size, and the height
* should bese on the layout xml file related to the custom view.
* @param context The context of the custom view.
* @return The pixel size of the height.
*/
int getPixelHeight(Context context);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment