[PCCT] Add close button position customization
Bug: 1318601
Change-Id: I834d6fa4147e9194c7e5c7a8f3332291f3c0ba27
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3600795
Reviewed-by: Peter Conn <peconn@chromium.org>
Reviewed-by: Jinsuk Kim <jinsukkim@chromium.org>
Commit-Queue: Sinan Sahin <sinansahin@google.com>
Cr-Commit-Position: refs/heads/main@{#997362}
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 48198f84..b4402d9d 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -269,7 +269,7 @@
<!-- Custom Tabs dimensions -->
<dimen name="custom_tabs_toolbar_maxWidth">60dp</dimen>
<dimen name="custom_tabs_toolbar_vertical_padding">16dp</dimen>
- <dimen name="custom_tabs_toolbar_horizontal_margin_no_close">8dp</dimen>
+ <dimen name="custom_tabs_toolbar_horizontal_margin_no_start">8dp</dimen>
<dimen name="min_toolbar_icon_side_padding">6dp</dimen>
<dimen name="custom_tabs_url_text_size">12sp</dimen>
<dimen name="custom_tabs_title_text_size">16sp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
index d958587..bde1c309 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
@@ -161,6 +161,7 @@
CustomTabToolbar toolbar = mActivity.findViewById(R.id.toolbar);
View coordinator = mActivity.findViewById(R.id.coordinator);
mCustomTabHeightStrategy.onToolbarInitialized(coordinator, toolbar);
+ toolbar.setCloseButtonPosition(mIntentDataProvider.get().getCloseButtonPosition());
}
@Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index 02b5adf1..8641b36 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -169,6 +169,13 @@
public static final String EXTRA_INITIAL_ACTIVITY_HEIGHT_IN_PIXEL =
"androidx.browser.customtabs.extra.INITIAL_ACTIVITY_HEIGHT_IN_PIXEL";
+ /**
+ * Extra that specifies the position of the close button on the toolbar. Default is
+ * {@link #CLOSE_BUTTON_POSITION_DEFAULT}.
+ */
+ public static final String EXTRA_CLOSE_BUTTON_POSITION =
+ "androidx.browser.customtabs.extra.CLOSE_BUTTON_POSITION";
+
private static final String DEFAULT_POLICY_PARAM_NAME = "default_policy";
private static final String DEFAULT_POLICY_USE_DENYLIST = "use-denylist";
private static final String DEFAULT_POLICY_USE_ALLOWLIST = "use-allowlist";
@@ -850,4 +857,10 @@
assert false : "We can't get here since the default policy is use denylist.";
return false;
}
+
+ @Override
+ public @CloseButtonPosition int getCloseButtonPosition() {
+ return IntentUtils.safeGetIntExtra(
+ mIntent, EXTRA_CLOSE_BUTTON_POSITION, CLOSE_BUTTON_POSITION_DEFAULT);
+ }
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
index 282605e..862e13b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.customtabs.features.toolbar;
import static org.chromium.base.MathUtils.interpolate;
+import static org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CLOSE_BUTTON_POSITION_END;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -25,16 +26,19 @@
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ActionMode;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt;
+import androidx.annotation.Dimension;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.content.res.AppCompatResources;
@@ -44,6 +48,7 @@
import org.chromium.base.supplier.Supplier;
import org.chromium.base.task.PostTask;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CloseButtonPosition;
import org.chromium.chrome.browser.crash.ChromePureJavaExceptionReporter;
import org.chromium.chrome.browser.omnibox.LocationBar;
import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
@@ -60,6 +65,7 @@
import org.chromium.chrome.browser.theme.ThemeUtils;
import org.chromium.chrome.browser.toolbar.LocationBarModel;
import org.chromium.chrome.browser.toolbar.ToolbarProgressBar;
+import org.chromium.chrome.browser.toolbar.menu_button.MenuButton;
import org.chromium.chrome.browser.toolbar.top.ToolbarLayout;
import org.chromium.chrome.browser.toolbar.top.ToolbarPhone;
import org.chromium.chrome.browser.ui.native_page.NativePage;
@@ -93,6 +99,7 @@
private ImageView mIncognitoImageView;
private LinearLayout mCustomActionButtons;
private ImageButton mCloseButton;
+ private MenuButton mMenuButton;
// This View will be non-null only for bottom sheet custom tabs.
private ImageView mHandleView;
@@ -138,6 +145,7 @@
}
private HandleStrategy mHandleStrategy;
+ private @CloseButtonPosition int mCloseButtonPosition;
/**
* Constructor for getting this class inflated from an xml layout file.
@@ -159,6 +167,7 @@
mCustomActionButtons = findViewById(R.id.action_buttons);
mCloseButton = findViewById(R.id.close_button);
mCloseButton.setOnLongClickListener(this);
+ mMenuButton = findViewById(R.id.menu_button_wrapper);
mLocationBar.onFinishInflate(this);
}
@@ -308,6 +317,14 @@
mLocationBar.showBranding();
}
+ /**
+ * Sets the close button position for this toolbar.
+ * @param closeButtonPosition The {@link CloseButtonPosition}.
+ */
+ public void setCloseButtonPosition(@CloseButtonPosition int closeButtonPosition) {
+ mCloseButtonPosition = closeButtonPosition;
+ }
+
private void updateButtonsTint() {
updateButtonTint(mCloseButton);
int numCustomActionButtons = mCustomActionButtons.getChildCount();
@@ -324,11 +341,45 @@
}
}
+ private void maybeSwapCloseAndMenuButtons() {
+ if (mCloseButtonPosition != CLOSE_BUTTON_POSITION_END) return;
+
+ final View closeButton = findViewById(R.id.close_button);
+ final int closeButtonIndex = indexOfChild(closeButton);
+ final ViewGroup.LayoutParams closeButtonLayoutParams = closeButton.getLayoutParams();
+ final View menuButton = findViewById(R.id.menu_button_wrapper);
+ final int menuButtonIndex = indexOfChild(menuButton);
+ final ViewGroup.LayoutParams menuButtonLayoutParams = menuButton.getLayoutParams();
+ removeViewAt(menuButtonIndex);
+ addView(menuButton, closeButtonIndex, menuButtonLayoutParams);
+ removeView(closeButton);
+ addView(closeButton, menuButtonIndex, closeButtonLayoutParams);
+ }
+
+ private void maybeAdjustButtonSpacingForCloseButtonPosition() {
+ if (mCloseButtonPosition != CLOSE_BUTTON_POSITION_END) return;
+
+ final @Dimension int buttonWidth =
+ getResources().getDimensionPixelSize(R.dimen.toolbar_button_width);
+ final FrameLayout.LayoutParams menuButtonLayoutParams =
+ (FrameLayout.LayoutParams) mMenuButton.getLayoutParams();
+ menuButtonLayoutParams.width = buttonWidth;
+ menuButtonLayoutParams.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
+ mMenuButton.setLayoutParams(menuButtonLayoutParams);
+ mMenuButton.setPaddingRelative(0, 0, 0, 0);
+
+ ((FrameLayout.LayoutParams) mCloseButton.getLayoutParams()).gravity =
+ Gravity.CENTER_VERTICAL | Gravity.END;
+
+ ((FrameLayout.LayoutParams) mCustomActionButtons.getLayoutParams())
+ .setMarginEnd(buttonWidth);
+ }
+
private void updateToolbarLayoutMargin() {
final boolean shouldShowIncognitoIcon = getToolbarDataProvider().isIncognito();
mIncognitoImageView.setVisibility(shouldShowIncognitoIcon ? VISIBLE : GONE);
- int startMargin = calculateStartMarginWhenCloseButtonVisibilityGone();
+ int startMargin = calculateStartMarginForStartButtonVisibility();
updateStartMarginOfVisibleElementsUntilLocationBarFrameLayout(startMargin);
@@ -341,10 +392,12 @@
mLocationBar.updateLeftMarginOfTitleUrlContainer();
}
- private int calculateStartMarginWhenCloseButtonVisibilityGone() {
- return (mCloseButton.getVisibility() == GONE) ? getResources().getDimensionPixelSize(
- R.dimen.custom_tabs_toolbar_horizontal_margin_no_close)
- : 0;
+ private int calculateStartMarginForStartButtonVisibility() {
+ final View buttonAtStart =
+ mCloseButtonPosition == CLOSE_BUTTON_POSITION_END ? mMenuButton : mCloseButton;
+ return (buttonAtStart.getVisibility() == GONE) ? getResources().getDimensionPixelSize(
+ R.dimen.custom_tabs_toolbar_horizontal_margin_no_start)
+ : 0;
}
private void updateStartMarginOfVisibleElementsUntilLocationBarFrameLayout(int startMargin) {
@@ -497,7 +550,9 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ maybeSwapCloseAndMenuButtons();
updateToolbarLayoutMargin();
+ maybeAdjustButtonSpacingForCloseButtonPosition();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java
index 34c4abe..68fe8a8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityRenderTest.java
@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.customtabs;
+import static org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CLOSE_BUTTON_POSITION_END;
+import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_CLOSE_BUTTON_POSITION;
import static org.chromium.chrome.browser.customtabs.CustomTabsTestUtils.createTestBitmap;
import android.app.PendingIntent;
@@ -176,6 +178,15 @@
@Test
@MediumTest
@Feature("RenderTest")
+ public void testCCTToolbarWithEndCloseButton() throws IOException {
+ mIntent.putExtra(EXTRA_CLOSE_BUTTON_POSITION, CLOSE_BUTTON_POSITION_END);
+
+ startActivityAndRenderToolbar("cct_close_button_end_with_https_" + mRunWithHttps);
+ }
+
+ @Test
+ @MediumTest
+ @Feature("RenderTest")
public void custom_color_red() throws IOException {
Context context = InstrumentationRegistry.getContext();
mIntent = CustomTabsTestUtils.createCustomTabIntent(
diff --git a/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/BrowserServicesIntentDataProvider.java b/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/BrowserServicesIntentDataProvider.java
index a69881f..bdf36b5 100644
--- a/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/BrowserServicesIntentDataProvider.java
+++ b/chrome/browser/android/browserservices/intents/java/src/org/chromium/chrome/browser/browserservices/intents/BrowserServicesIntentDataProvider.java
@@ -57,6 +57,25 @@
int V2_NOTIFICATION_OR_SNACKBAR = 1;
}
+ @IntDef({CLOSE_BUTTON_POSITION_DEFAULT, CLOSE_BUTTON_POSITION_START, CLOSE_BUTTON_POSITION_END})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CloseButtonPosition {}
+
+ /** Same as {@link #CLOSE_BUTTON_POSITION_START}. */
+ public static final int CLOSE_BUTTON_POSITION_DEFAULT = 0;
+
+ /** Positions the close button at the start of the toolbar. */
+ public static final int CLOSE_BUTTON_POSITION_START = 1;
+
+ /** Positions the close button at the end of the toolbar. */
+ public static final int CLOSE_BUTTON_POSITION_END = 2;
+
+ /**
+ * Maximum value for the CLOSE_BUTTON_POSITION_* configuration options. For validation purposes
+ * only.
+ */
+ public static final int CLOSE_BUTTON_POSITION_MAX = 2;
+
/**
* @return The type of the Activity;
*/
@@ -456,4 +475,11 @@
public @Px int getInitialActivityHeight() {
return 0;
}
+
+ /**
+ * Returns the {@link CloseButtonPosition}.
+ */
+ public @CloseButtonPosition int getCloseButtonPosition() {
+ return CLOSE_BUTTON_POSITION_DEFAULT;
+ }
}