Bug 1348718 - Build option menu button in same way
There might be up to 2 Always-show-as-action button in ActionBar.
One for menu-options, one for 3rd-party app action-button, if any.
According to our design spec, the two buttons appearance should be
similiar, therefore now we create them by same method.
MozReview-Commit-ID: GPVteQR3hxr
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
@@ -11,22 +11,27 @@ import android.graphics.drawable.ColorDr
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.TextView;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SiteIdentity;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.toolbar.SecurityModeUtil;
import org.mozilla.gecko.toolbar.SiteIdentityPopup;
import org.mozilla.gecko.util.ColorUtil;
@@ -104,16 +109,51 @@ public class ActionBarPresenter {
public void run() {
updateCustomView(tab.getSiteIdentity(), title, url);
}
};
mHandler.postDelayed(mUpdateAction, CUSTOM_VIEW_UPDATE_DELAY);
}
/**
+ * To add a always-show-as-action button to menu, and manually create a view to insert.
+ *
+ * @param menu the menu to insert new action-button.
+ * @param icon the image to be used for action-button.
+ * @param tint true if the icon should be tint by primary text color
+ * @return the view which be inserted to menu
+ */
+ public View addActionButton(@NonNull final Menu menu,
+ @NonNull final Drawable icon,
+ final boolean tint) {
+ final Resources res = mActionBar.getThemedContext().getResources();
+
+ // if we specify layout_width, layout_height in xml to build View, then add to ActionBar
+ // system might overwrite the value to WRAP_CONTENT.
+ // Therefore we create view manually to match design spec
+ final ImageButton btn = new ImageButton(mActionBar.getThemedContext(), null, 0);
+ final int size = res.getDimensionPixelSize(R.dimen.custom_tab_action_button_size);
+ final int padding = res.getDimensionPixelSize(R.dimen.custom_tab_action_button_padding);
+ btn.setPadding(padding, padding, padding, padding);
+ btn.setLayoutParams(new ViewGroup.LayoutParams(size, size));
+ btn.setScaleType(ImageView.ScaleType.FIT_CENTER);
+
+ if (tint) {
+ DrawableCompat.setTint(icon, mTextPrimaryColor);
+ }
+ btn.setImageDrawable(icon);
+
+ // menu id does not matter here. We can directly bind callback to the returned-view.
+ final MenuItem item = menu.add(Menu.NONE, -1, Menu.NONE, "");
+ item.setActionView(btn);
+ MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
+ return btn;
+ }
+
+ /**
* Set background color to ActionBar, as well as Status bar.
*
* @param color the color to apply to ActionBar
* @param window Window instance for changing color status bar, or null if won't change it.
*/
@UiThread
public void setBackgroundColor(@ColorInt final int color,
@Nullable final Window window) {
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -11,51 +11,45 @@ import android.content.pm.PackageManager
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
-import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.StyleRes;
-import android.support.annotation.VisibleForTesting;
import android.support.design.widget.Snackbar;
-import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.util.SparseArrayCompat;
-import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ImageButton;
import android.widget.ProgressBar;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SnackbarBuilder;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.GeckoMenuInflater;
import org.mozilla.gecko.util.Clipboard;
import org.mozilla.gecko.util.ColorUtil;
+import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.IntentUtils;
import org.mozilla.gecko.widget.GeckoPopupMenu;
-import org.mozilla.gecko.util.GeckoBundle;
import java.util.List;
public class CustomTabsActivity extends GeckoApp implements Tabs.OnTabsChangedListener {
private static final String LOGTAG = "CustomTabsActivity";
private static final String SAVED_START_INTENT = "saved_intent_which_started_this_activity";
private final SparseArrayCompat<PendingIntent> menuItemsIntent = new SparseArrayCompat<>();
@@ -213,50 +207,52 @@ public class CustomTabsActivity extends
}
// Usually should use onCreateOptionsMenu() to initialize menu items. But GeckoApp overwrite
// it to support custom menu(Bug 739412). Then the parameter *menu* in this.onCreateOptionsMenu()
// and this.onPrepareOptionsMenu() are different instances - GeckoApp.onCreatePanelMenu() changed it.
// CustomTabsActivity only use standard menu in ActionBar, so initialize menu here.
@Override
public boolean onCreatePanelMenu(final int id, final Menu menu) {
- insertActionButton(menu, startIntent, actionBarPresenter.getTextPrimaryColor());
-
- popupMenu = createCustomPopupMenu();
- // Create a ImageButton manually, and use it as an anchor for PopupMenu.
- final ImageButton btn = new ImageButton(getContext(),
- null, 0, R.style.Widget_MenuButtonCustomTabs);
- btn.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View anchor) {
- popupMenu.setAnchor(anchor);
- popupMenu.show();
- }
- });
+ // if 3rd-party app asks to add an action button
+ if (IntentUtil.hasActionButton(startIntent)) {
+ final Bitmap bitmap = IntentUtil.getActionButtonIcon(startIntent);
+ final Drawable icon = new BitmapDrawable(getResources(), bitmap);
+ final boolean shouldTint = IntentUtil.isActionButtonTinted(startIntent);
+ actionBarPresenter.addActionButton(menu, icon, shouldTint)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onActionButtonClicked();
+ }
+ });
+ }
- // Insert the anchor-button to Menu
- final MenuItem item = menu.add(Menu.NONE, R.id.menu, Menu.NONE, "Menu Button");
- item.setActionView(btn);
- MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
+ // insert an action button for menu. click it to show popup menu
+ popupMenu = createCustomPopupMenu();
+ actionBarPresenter.addActionButton(menu, getDrawable(R.drawable.ab_menu), true)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View anchor) {
+ popupMenu.setAnchor(anchor);
+ popupMenu.show();
+ }
+ });
updateMenuItemForward();
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
- case R.id.action_button:
- onActionButtonClicked();
- return true;
case R.id.share:
onShareClicked();
return true;
case R.id.custom_tabs_menu_forward:
onForwardClicked();
return true;
case R.id.custom_tabs_menu_reload:
onReloadClicked();
@@ -270,47 +266,16 @@ public class CustomTabsActivity extends
if (intent != null) {
performPendingIntent(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
- /**
- * To insert a MenuItem (as an ActionButton) into Menu.
- *
- * @param menu The options menu in which to place items.
- * @param intent which to launch this activity
- * @param tintColor color to tint action-button
- * @return the MenuItem which be created and inserted into menu. Otherwise, null.
- */
- @VisibleForTesting
- MenuItem insertActionButton(final Menu menu,
- final Intent intent,
- @ColorInt final int tintColor) {
- if (!IntentUtil.hasActionButton(intent)) {
- return null;
- }
-
- MenuItem item = menu.add(Menu.NONE,
- R.id.action_button,
- Menu.NONE,
- IntentUtil.getActionButtonDescription(intent));
- Bitmap bitmap = IntentUtil.getActionButtonIcon(intent);
- final Drawable icon = new BitmapDrawable(getResources(), bitmap);
- if (IntentUtil.isActionButtonTinted(intent)) {
- DrawableCompat.setTint(icon, tintColor);
- }
- item.setIcon(icon);
- MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
-
- return item;
- }
-
private void bindNavigationCallback(@NonNull final Toolbar toolbar) {
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Tabs tabs = Tabs.getInstance();
final Tab tab = tabs.getSelectedTab();
tabs.closeTab(tab);
finish();
new file mode 100644
index 0000000000000000000000000000000000000000..2c7718576a4973bcc41af02af496d16528488363
GIT binary patch
literal 469
zc$@*%0V@89P)<h;3K|Lk000e1NJLTq001Na001Ni1^@s6;Q*MJ00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10a8gsK~z|U?U&6;13?gkYqYC1{-6O5>nj*f`kMZ{fdqU9iFpT?
zoQ=l>_24fm$V?J18wg<#oDNKo{h%+kY*Da7Z4XdW^UrV#@K_g-BLD~?+yMAqfM*)2
zdPwq)<fNLus<yHPBH5b>Go8}nY58OY$@|y??|lK_F~xMn5a=C1i0C5#AE~C6KwkhZ
zBYGRar@_}mgXF1*3`Ar=@&rI5SD2c=(5xmq`>J|9?I2a{04TDhA=#ZT#wt`YmSSv@
ze2REXy!U$mo>NRMJ@gyn)E6y*UYv8?dC@u70q|<@HBqQ)hvb;#SXHl(^H9&QTTRW<
zvqAD)M1~?VBzcCMKUb3N$i{eK@w61<CdoGdt8@Cud%uIkoygKd+mSG+w5?QAOP~h;
zy@*~Sai2D$sx6ZJne%h2ss|R&MO+luMC2I2B!o~R=S8umW*PYbm+@1A_T9QZ00000
LNkvXXu0mjfP4&a5
new file mode 100644
index 0000000000000000000000000000000000000000..4b21c1cc0bd91c8859f44ec68a31acb5a14d6fed
GIT binary patch
literal 660
zc$@*00&D$=P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10uf0>K~!jg?U~JL6hRb)Pj}ZjGbZ3pQ9&WdBnt_;6hYrZBH8)^
z;sdyFCn6}mg+H(06KHmde?b!$ZW3`!r+d1}O)Dcz&qTfDM5qsH)3@kzs`^q@eG5n=
z5{blLki~j&uh$!R?=J&Dp6Ac@_xE4N(z3>pd`Qxh3~g&jJ^)b6+uTef-5xXkOOtfV
zTF*L#7D#>uu+R}7)^&Xhz@C+0ZuKGnAUQy{c>q|HG_ce(9Y9eOUuFvC`L3m==>W>I
zd<S4-N|)zlS#DZtnhv1lI)HBzo)6pD;YZS{bM7(89g;iFxkr-D&D&QZF@b1jApnJ>
z6#%HJ>Lq|CqLwWr*Cl-#J3?$rx;AfL2ZH4Kl(W#9wVrhf6_P%N5Kc@Ah7h(#qtO`{
zrjzMLCTXS1JOE@_c1qH+rDlws_@5FZg+7E3PEHE8DRdfuw-U7e0u6whonm=@1BT|K
zA!*GyxAkN7an5Z?x*9_(_C~f0AXHWL3jf2*ClW@GJnx))N^-aTp?M-{b>6-Xgmdl^
z$>D^v(2(RsYd!N-h~x%<uGxN3*YyQUJ<|d7`~9V+Y2HrjQxwHgS(fjuG);HnrfH7O
z>f^ni+2?n#PN5@hX>qY5{<W^_<2bCPMF4wQmfh_NW?6OzhUQ~Yki6fP)W^%~_Yk4H
u9`l0ZtoQy3@biM>O)RZMB9Tb^G2a0mL!3nq&#y-S0000<MNUMnLSTX$s33X(
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -229,9 +229,13 @@
<item name="activity_stream_base_margin" type="dimen">10dp</item>
<item name="activity_stream_desired_tile_width" type="dimen">90dp</item>
<item name="activity_stream_desired_tile_height" type="dimen">70dp</item>
<item name="activity_stream_top_sites_text_height" type="dimen">30dp</item>
<!-- Default touch target size for buttons/imageviews that might be of small size -->
<item name="touch_target_size" type="dimen">48dp</item>
+
+ <!-- Custom tabs -->
+ <dimen name="custom_tab_action_button_size">56dp</dimen>
+ <dimen name="custom_tab_action_button_padding">16dp</dimen>
</resources>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -114,20 +114,16 @@
<item name="android:drawablePadding">6dip</item>
<item name="android:gravity">center_vertical</item>
<item name="android:textAppearance">@style/TextAppearance</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">middle</item>
<item name="android:textSize">@dimen/menu_item_textsize</item>
</style>
- <style name="Widget.MenuButtonCustomTabs" parent="GeckoActionBar.Button.MenuButton">
- <item name="android:tint">?android:textColorPrimary</item>
- </style>
-
<style name="Widget.MenuItemCustomTabs" parent="Widget.MenuItemDefault">
<!-- In current design, there is only one style for Popup-menu, regardless of Dark/Light theme -->
<item name="android:textColor">@android:color/black</item>
<item name="android:textColorHighlight">?android:textColorHighlight</item>
<item name="android:textColorHint">?android:attr/textColorHint</item>
<item name="android:textColorLink">?android:attr/textColorLink</item>
</style>
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/customtabs/TestCustomTabsActivity.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/customtabs/TestCustomTabsActivity.java
@@ -95,36 +95,9 @@ public class TestCustomTabsActivity {
builder.setExitAnimations(spyContext, enterRes, exitRes);
final Intent i = builder.build().intent;
Whitebox.setInternalState(spyActivity, "usingCustomAnimation", true);
Whitebox.setInternalState(spyActivity, "startIntent", i);
Assert.assertEquals(THIRD_PARTY_PACKAGE_NAME, spyActivity.getPackageName());
}
-
- @Test
- public void testInsertActionButton() {
- // create properties for CustomTabsIntent
- final String description = "Description";
- final Intent actionIntent = new Intent(Intent.ACTION_VIEW);
- final int reqCode = 0x123;
- final PendingIntent pendingIntent = PendingIntent.getActivities(spyContext,
- reqCode,
- new Intent[]{actionIntent},
- PendingIntent.FLAG_CANCEL_CURRENT);
- final Bitmap bitmap = BitmapFactory.decodeResource(
- spyContext.getResources(),
- R.drawable.ic_action_settings); // arbitrary icon resource
-
- // To create a CustomTabsIntent which is asking for ActionButton.
- final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
- builder.setActionButton(bitmap, description, pendingIntent, true);
-
- // CustomTabsActivity should return a MenuItem with corresponding attributes.
- Menu menu = new RoboMenu(spyContext);
- MenuItem item = spyActivity.insertActionButton(menu, builder.build().intent, 0xFF0000);
- Assert.assertNotNull(item);
- Assert.assertEquals(item.getTitle(), description);
- Assert.assertEquals(0, item.getOrder()); // should be the first one
- Assert.assertTrue(item.isVisible());
- }
}
\ No newline at end of file