Commit bc8147b7 authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: Handles the case of gesture navigation closing tab

There are situations where back button closes the current tab.
Gesture navigation also need to do what back button does in this
case. This CL shows close indicator "Close Tab", and does not
open the navigation sheet.

Bug: 1009059
Change-Id: Ife4f53bb41253646d18feb1cf5e2c50a04b1d2ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1885135Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarJinsuk Kim <jinsukkim@chromium.org>
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710628}
parent 6a2e670a
...@@ -17,16 +17,33 @@ import android.widget.LinearLayout; ...@@ -17,16 +17,33 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.ColorUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** /**
* View class for a bubble used in gesture navigation UI that consists of an icon * View class for a bubble used in gesture navigation UI that consists of an icon
* and an optional text. * and an optional text.
*/ */
public class NavigationBubble extends LinearLayout { public class NavigationBubble extends LinearLayout {
/**
* Target to close when gesture navigation takes place on the beginning
* of the navigation history. It can close either the current tab or
* chrome itself (putting it background).
*/
@IntDef({CloseTarget.NONE, CloseTarget.TAB, CloseTarget.APP})
@Retention(RetentionPolicy.SOURCE)
@interface CloseTarget {
int NONE = 0;
int TAB = 1;
int APP = 2;
}
private static final int COLOR_TRANSITION_DURATION_MS = 250; private static final int COLOR_TRANSITION_DURATION_MS = 250;
private static final float FADE_ALPHA = 0.5f; private static final float FADE_ALPHA = 0.5f;
...@@ -36,6 +53,8 @@ public class NavigationBubble extends LinearLayout { ...@@ -36,6 +53,8 @@ public class NavigationBubble extends LinearLayout {
private final ValueAnimator mColorAnimator; private final ValueAnimator mColorAnimator;
private final int mBlue; private final int mBlue;
private final int mBlack; private final int mBlack;
private final String mCloseApp;
private final String mCloseTab;
private class ColorUpdateListener implements ValueAnimator.AnimatorUpdateListener { private class ColorUpdateListener implements ValueAnimator.AnimatorUpdateListener {
private int mStart; private int mStart;
...@@ -63,6 +82,8 @@ public class NavigationBubble extends LinearLayout { ...@@ -63,6 +82,8 @@ public class NavigationBubble extends LinearLayout {
// True if arrow bubble is faded out. // True if arrow bubble is faded out.
private boolean mArrowFaded; private boolean mArrowFaded;
private @CloseTarget int mCloseTarget;
/** /**
* Constructor for inflating from XML. * Constructor for inflating from XML.
*/ */
...@@ -88,6 +109,10 @@ public class NavigationBubble extends LinearLayout { ...@@ -88,6 +109,10 @@ public class NavigationBubble extends LinearLayout {
getBackground().setColorFilter(ApiCompatibilityUtils.getColor(getResources(), getBackground().setColorFilter(ApiCompatibilityUtils.getColor(getResources(),
R.color.navigation_bubble_background_color), R.color.navigation_bubble_background_color),
Mode.MULTIPLY); Mode.MULTIPLY);
mCloseApp = getResources().getString(R.string.overscroll_navigation_close_chrome,
getContext().getString(R.string.app_name));
mCloseTab = getResources().getString(R.string.overscroll_navigation_close_tab);
mCloseTarget = CloseTarget.NONE;
} }
@Override @Override
...@@ -114,19 +139,27 @@ public class NavigationBubble extends LinearLayout { ...@@ -114,19 +139,27 @@ public class NavigationBubble extends LinearLayout {
} }
/** /**
* Shows or hides the close chrome indicator. * Shows or hides the close indicator.
* @param on {@code true} if the indicator should appear. * @param target Target to close. if {@code NONE}, hide the indicator.
*/ */
public void showCaption(boolean on) { public void showCaption(@CloseTarget int target) {
if (on && !isShowingCaption()) { if (target != CloseTarget.NONE && !isShowingCaption()) {
setCloseIndicator(target);
getTextView().setVisibility(View.VISIBLE); getTextView().setVisibility(View.VISIBLE);
// Measure the width again after the indicator text becomes visible. // Measure the width again after the indicator text becomes visible.
measure(0, 0); measure(0, 0);
} else if (!on && isShowingCaption()) { } else if (target == CloseTarget.NONE && isShowingCaption()) {
getTextView().setVisibility(View.GONE); getTextView().setVisibility(View.GONE);
} }
} }
private void setCloseIndicator(@CloseTarget int target) {
assert target == CloseTarget.APP || target == CloseTarget.TAB;
if (mCloseTarget == target) return;
mCloseTarget = target;
getTextView().setText(target == CloseTarget.APP ? mCloseApp : mCloseTab);
}
@Override @Override
public void onAnimationStart() { public void onAnimationStart() {
super.onAnimationStart(); super.onAnimationStart();
......
...@@ -15,6 +15,7 @@ import androidx.annotation.IntDef; ...@@ -15,6 +15,7 @@ import androidx.annotation.IntDef;
import org.chromium.base.Supplier; import org.chromium.base.Supplier;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.gesturenav.NavigationBubble.CloseTarget;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
...@@ -84,6 +85,11 @@ public class NavigationHandler { ...@@ -84,6 +85,11 @@ public class NavigationHandler {
*/ */
void navigate(boolean forward); void navigate(boolean forward);
/**
* @return {@code true} if back action will close the current tab.
*/
boolean willBackCloseTab();
/** /**
* @return {@code true} if back action will cause the app to exit. * @return {@code true} if back action will cause the app to exit.
*/ */
...@@ -192,11 +198,12 @@ public class NavigationHandler { ...@@ -192,11 +198,12 @@ public class NavigationHandler {
if (mSideSlideLayout == null) createLayout(); if (mSideSlideLayout == null) createLayout();
mSideSlideLayout.setEnabled(true); mSideSlideLayout.setEnabled(true);
mSideSlideLayout.setDirection(forward); mSideSlideLayout.setDirection(forward);
boolean showCloseIndicator = shouldShowCloseIndicator(forward); @CloseTarget
mSideSlideLayout.setEnableCloseIndicator(showCloseIndicator); int closeIndicator = getCloseIndicator(forward);
mSideSlideLayout.setCloseIndicator(closeIndicator);
attachLayoutIfNecessary(); attachLayoutIfNecessary();
mSideSlideLayout.start(); mSideSlideLayout.start();
mNavigationSheet.start(forward, showCloseIndicator); mNavigationSheet.start(forward, closeIndicator != CloseTarget.NONE);
mState = GestureState.DRAGGED; mState = GestureState.DRAGGED;
} }
...@@ -218,6 +225,18 @@ public class NavigationHandler { ...@@ -218,6 +225,18 @@ public class NavigationHandler {
return !forward && mActionDelegate.willBackExitApp(); return !forward && mActionDelegate.willBackExitApp();
} }
private @CloseTarget int getCloseIndicator(boolean forward) {
// Some tabs, upon back at the beginning of the history stack, should be just closed
// than closing the entire app.
if (!forward && mActionDelegate.willBackCloseTab()) {
return CloseTarget.TAB;
} else if (!forward && mActionDelegate.willBackExitApp()) {
return CloseTarget.APP;
} else {
return CloseTarget.NONE;
}
}
/** /**
* Signals a pull update. * Signals a pull update.
* @param delta The change in horizontal pull distance (positive if toward right, * @param delta The change in horizontal pull distance (positive if toward right,
......
...@@ -18,6 +18,7 @@ import android.view.animation.ScaleAnimation; ...@@ -18,6 +18,7 @@ import android.view.animation.ScaleAnimation;
import android.view.animation.Transformation; import android.view.animation.Transformation;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.gesturenav.NavigationBubble.CloseTarget;
import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.ui.widget.animation.Interpolators;
/** /**
...@@ -95,7 +96,7 @@ public class SideSlideLayout extends ViewGroup { ...@@ -95,7 +96,7 @@ public class SideSlideLayout extends ViewGroup {
private int mAnimationViewWidth; private int mAnimationViewWidth;
private boolean mIsForward; private boolean mIsForward;
private boolean mCloseIndicatorEnabled; private @CloseTarget int mCloseIndicator;
// True while swiped to a distance where, if released, the navigation would be triggered. // True while swiped to a distance where, if released, the navigation would be triggered.
private boolean mWillNavigate; private boolean mWillNavigate;
...@@ -224,8 +225,8 @@ public class SideSlideLayout extends ViewGroup { ...@@ -224,8 +225,8 @@ public class SideSlideLayout extends ViewGroup {
forward ? R.drawable.ic_arrow_forward_blue_24dp : R.drawable.ic_arrow_back_24dp); forward ? R.drawable.ic_arrow_forward_blue_24dp : R.drawable.ic_arrow_back_24dp);
} }
public void setEnableCloseIndicator(boolean enable) { public void setCloseIndicator(@CloseTarget int target) {
mCloseIndicatorEnabled = enable; mCloseIndicator = target;
} }
@Override @Override
...@@ -303,9 +304,9 @@ public class SideSlideLayout extends ViewGroup { ...@@ -303,9 +304,9 @@ public class SideSlideLayout extends ViewGroup {
} }
mWillNavigate = navigating; mWillNavigate = navigating;
if (mCloseIndicatorEnabled) { if (mCloseIndicator != CloseTarget.NONE) {
if (mWillNavigate) { if (mWillNavigate) {
mArrowView.showCaption(true); mArrowView.showCaption(mCloseIndicator);
mArrowViewWidth = mArrowView.getMeasuredWidth(); mArrowViewWidth = mArrowView.getMeasuredWidth();
} else { } else {
hideCloseIndicator(); hideCloseIndicator();
...@@ -343,7 +344,7 @@ public class SideSlideLayout extends ViewGroup { ...@@ -343,7 +344,7 @@ public class SideSlideLayout extends ViewGroup {
} }
private void hideCloseIndicator() { private void hideCloseIndicator() {
mArrowView.showCaption(false); mArrowView.showCaption(CloseTarget.NONE);
// The width when indicator text view is hidden is slightly bigger than the height. // The width when indicator text view is hidden is slightly bigger than the height.
// Set the width to circle's diameter for the widget to be of completely round shape. // Set the width to circle's diameter for the widget to be of completely round shape.
mArrowViewWidth = mCircleWidth; mArrowViewWidth = mCircleWidth;
......
...@@ -39,6 +39,11 @@ public class TabbedActionDelegate implements NavigationHandler.ActionDelegate { ...@@ -39,6 +39,11 @@ public class TabbedActionDelegate implements NavigationHandler.ActionDelegate {
} }
} }
@Override
public boolean willBackCloseTab() {
return !mTab.canGoBack() && mTab.getActivity().backShouldCloseTab(mTab);
}
@Override @Override
public boolean willBackExitApp() { public boolean willBackExitApp() {
return !mTab.canGoBack() return !mTab.canGoBack()
......
...@@ -3350,6 +3350,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p ...@@ -3350,6 +3350,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_OVERSCROLL_NAVIGATION_CLOSE_CHROME" desc="Message displayed on overscroll navigation UI widget when the back navigation is attempted at the beginning of navigation history stack. The widget only has an arrow icon but expands to display this message next to it."> <message name="IDS_OVERSCROLL_NAVIGATION_CLOSE_CHROME" desc="Message displayed on overscroll navigation UI widget when the back navigation is attempted at the beginning of navigation history stack. The widget only has an arrow icon but expands to display this message next to it.">
Close <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph> Close <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph>
</message> </message>
<message name="IDS_OVERSCROLL_NAVIGATION_CLOSE_TAB" desc="Message displayed on overscroll navigation UI widget when the back navigation is attempted at the beginning of navigation history stack. The widget only has an arrow icon but expands to display this message next to it.">
Close tab
</message>
<message name="IDS_OVERSCROLL_NAVIGATION_SHEET_DESCRIPTION" desc="The content description of the navigation bottom sheet."> <message name="IDS_OVERSCROLL_NAVIGATION_SHEET_DESCRIPTION" desc="The content description of the navigation bottom sheet.">
Navigation history Navigation history
</message> </message>
......
ecf313d305d56db7c25dcb3fd5882cbd74ee23d6
\ No newline at end of file
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