Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java |
index 93a70054e7c78a29c3137ee0d8a853ff65ab7efa..db12da124e2c9f0c884f82ac374654ff1d6e4480 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java |
@@ -98,6 +98,17 @@ |
private static final float SEARCH_ICON_PADDING_LEFT_DP = 16.f; |
/** |
+ * The height of the promo state Contextual Search Panel search bar, in dps. |
+ */ |
+ private static final float SEARCH_BAR_HEIGHT_STATE_PROMO = 24.f; |
+ |
+ /** |
+ * How much the Promo Panel should displace in order to make some elements |
+ * invisible (like the Search Provider Icon and the Search Bar Text). |
+ */ |
+ private static final float DISAPPEARING_ELEMENT_THRESHOLD_DP = 10.f; |
+ |
+ /** |
* The height of the Search Bar's border in dps. |
*/ |
private static final float SEARCH_BAR_BORDER_HEIGHT_DP = 1.f; |
@@ -122,6 +133,11 @@ |
private final float mSearchBarHeightPeeking; |
/** |
+ * The height of the Search Bar when the Panel is displaying the Promo, in dps. |
+ */ |
+ private final float mSearchBarHeightPromo; |
+ |
+ /** |
* The height of the Search Bar when the Panel is expanded, in dps. |
*/ |
private final float mSearchBarHeightExpanded; |
@@ -146,6 +162,12 @@ |
* in view when the Search Panel is in its EXPANDED state. |
*/ |
private float mBasePageTargetY = 0.f; |
+ |
+ /** |
+ * The Y coordinate to apply to the Base Page in order to keep the selection |
+ * in view when the Search Panel is in its PROMO state. |
+ */ |
+ private float mPromoBasePageTargetY = 0.f; |
/** |
* Whether the Panel is showing. |
@@ -174,6 +196,7 @@ |
mSearchBarHeightMaximized = TOOLBAR_HEIGHT_DP + PANEL_SHADOW_HEIGHT_DP; |
mSearchBarHeightExpanded = |
Math.round((mSearchBarHeightPeeking + mSearchBarHeightMaximized) / 2.f); |
+ mSearchBarHeightPromo = SEARCH_BAR_HEIGHT_STATE_PROMO + PANEL_SHADOW_HEIGHT_DP; |
initializeUiState(); |
} |
@@ -199,7 +222,7 @@ |
/** |
* @return Whether the Panel Promo is available. |
*/ |
- protected abstract boolean isPromoAvailable(); |
+ protected abstract boolean isPanelPromoAvailable(); |
/** |
* Animates the acceptance of the Promo. |
@@ -595,6 +618,42 @@ |
return Math.round((getOffsetY() + getSearchBarHeight()) / mPxToDp); |
} |
+ // -------------------------------------------------------------------------------------------- |
+ // Opt In Promo states |
+ // -------------------------------------------------------------------------------------------- |
+ |
+ private float mPromoContentHeight; |
+ private boolean mShouldHidePromoHeader; |
+ |
+ /** |
+ * Sets the height of the promo content. |
+ */ |
+ protected void setPromoContentHeight(float height) { |
+ mPromoContentHeight = height; |
+ updateBasePageTargetY(); |
+ } |
+ |
+ /** |
+ * Gets the height of the promo content, or -1 if height has not been calculated. |
+ */ |
+ public float getPromoContentHeight() { |
+ return mPromoContentHeight > 0.0f ? mPromoContentHeight : -1.f; |
+ } |
+ |
+ /** |
+ * @param shouldHidePromoHeader Sets whether the promo's header should be hidden. |
+ */ |
+ protected void setShouldHidePromoHeader(boolean shouldHidePromoHeader) { |
+ mShouldHidePromoHeader = shouldHidePromoHeader; |
+ } |
+ |
+ /** |
+ * @return Gets whether the promo's header should be hidden. |
+ */ |
+ public boolean shouldHidePromoHeader() { |
+ return mShouldHidePromoHeader; |
+ } |
+ |
// ============================================================================================ |
// Helpers |
// ============================================================================================ |
@@ -633,6 +692,9 @@ |
panelHeight = 0; |
} else if (state == PanelState.PEEKED) { |
panelHeight = mSearchBarHeightPeeking; |
+ } else if (state == PanelState.PROMO) { |
+ panelHeight = getPromoContentHeight() |
+ + mSearchBarHeightPromo; |
} else if (state == PanelState.EXPANDED) { |
panelHeight = fullscreenHeight * EXPANDED_PANEL_HEIGHT_PERCENTAGE |
+ PANEL_SHADOW_HEIGHT_DP; |
@@ -679,7 +741,7 @@ |
*/ |
protected void setClampedPanelHeight(float height) { |
final float clampedHeight = MathUtils.clamp(height, |
- getPanelHeightFromState(PanelState.MAXIMIZED), |
+ getPanelHeightFromState(getMaximumState()), |
getPanelHeightFromState(PanelState.PEEKED)); |
setPanelHeight(clampedHeight); |
} |
@@ -690,7 +752,7 @@ |
if (state == PanelState.CLOSED) { |
mIsShowing = false; |
- destroyPromoView(); |
+ destroySearchPromo(); |
destroyContextualSearchControl(); |
onClose(); |
} else if (state == PanelState.EXPANDED) { |
@@ -743,6 +805,8 @@ |
updatePanelForExpansion(percentage); |
} else if (endState == PanelState.MAXIMIZED) { |
updatePanelForMaximization(percentage); |
+ } else if (endState == PanelState.PROMO) { |
+ updatePanelForOpeningPromo(percentage); |
} |
} |
@@ -961,6 +1025,57 @@ |
} |
/** |
+ * Updates the UI state for the peeked to promo transition (and vice versa), |
+ * according to a completion |percentage|. |
+ * |
+ * @param percentage The completion percentage. |
+ */ |
+ private void updatePanelForOpeningPromo(float percentage) { |
+ // Base page offset. |
+ float baseBaseY = MathUtils.interpolate( |
+ 0, |
+ getPromoBasePageOffsetY(), |
+ percentage); |
+ mBasePageY = baseBaseY; |
+ |
+ // Base page brightness. |
+ float brightness = MathUtils.interpolate( |
+ BASE_PAGE_BRIGHTNESS_STATE_PEEKED, |
+ BASE_PAGE_BRIGHTNESS_STATE_EXPANDED, |
+ percentage); |
+ mBasePageBrightness = brightness; |
+ |
+ // Search Bar height. |
+ float searchBarHeight = Math.round(MathUtils.interpolate( |
+ mSearchBarHeightPeeking, |
+ mSearchBarHeightPromo, |
+ percentage)); |
+ mSearchBarHeight = searchBarHeight; |
+ |
+ // Search Bar border. |
+ mIsSearchBarBorderVisible = false; |
+ |
+ // Search Bar text opacity. |
+ float peekedHeight = getPanelHeightFromState(PanelState.PEEKED); |
+ float threshold = DISAPPEARING_ELEMENT_THRESHOLD_DP / mPxToDp; |
+ float diff = Math.min(mHeight - peekedHeight, threshold); |
+ float disappearingElementOpacity = MathUtils.interpolate(1.f, 0.f, diff / threshold); |
+ mSearchBarTextOpacity = disappearingElementOpacity; |
+ |
+ // Search provider icon opacity. |
+ boolean shouldDisplaySearchProviderIcon = shouldHidePromoHeader(); |
+ mSearchProviderIconOpacity = |
+ shouldDisplaySearchProviderIcon ? 1.f : disappearingElementOpacity; |
+ |
+ // Search icon opacity. |
+ mSearchIconOpacity = SEARCH_ICON_OPACITY_PEEKED; |
+ |
+ // Progress Bar. |
+ mProgressBarOpacity = 0.f; |
+ mProgressBarY = searchBarHeight - PROGRESS_BAR_HEIGHT_DP + 1; |
+ } |
+ |
+ /** |
* Updates the UI state for Opt Out Promo. |
* |
* @param percentage The visibility percentage of the Promo. A visibility of 0 means the |
@@ -968,7 +1083,7 @@ |
* visibility between 0 and 1 means the Promo is partially visible. |
*/ |
private void updatePromoVisibility(float percentage) { |
- if (isPromoAvailable()) { |
+ if (isPanelPromoAvailable()) { |
mPromoVisible = true; |
mPromoHeightPx = Math.round(MathUtils.clamp(percentage * mPromoContentHeightPx, |
@@ -1016,6 +1131,7 @@ |
*/ |
private void updateBasePageTargetY() { |
mBasePageTargetY = calculateBasePageTargetY(PanelState.EXPANDED); |
+ mPromoBasePageTargetY = calculateBasePageTargetY(PanelState.PROMO); |
} |
/** |
@@ -1062,6 +1178,14 @@ |
return mBasePageTargetY; |
} |
+ /** |
+ * @return The Y coordinate to apply to the Base Page in order to keep the |
+ * selection in view when the Search Panel is in PROMO state. |
+ */ |
+ private float getPromoBasePageOffsetY() { |
+ return mPromoBasePageTargetY; |
+ } |
+ |
// ============================================================================================ |
// Resource Loader |
// ============================================================================================ |
@@ -1080,9 +1204,9 @@ |
mControl.getResourceAdapter()); |
} |
- if (mPromoView != null) { |
+ if (mSearchPromoView != null) { |
mResourceLoader.registerResource(R.id.contextual_search_opt_out_promo, |
- mPromoView.getResourceAdapter()); |
+ mSearchPromoView.getResourceAdapter()); |
} |
} |
@@ -1149,7 +1273,6 @@ |
new Handler().post(new Runnable() { |
@Override |
public void run() { |
- setIsPromoActive(false); |
PreferencesLauncher.launchSettingsPage(mContext, |
ContextualSearchPreferenceFragment.class.getName()); |
} |
@@ -1177,7 +1300,7 @@ |
/** |
* The {@link ContextualSearchOptOutPromo} instance. |
*/ |
- private ContextualSearchOptOutPromo mPromoView; |
+ private ContextualSearchOptOutPromo mSearchPromoView; |
/** |
* Whether the Search Promo View is visible. |
@@ -1187,37 +1310,38 @@ |
/** |
* Creates the Search Promo View. |
*/ |
- public void createPromoView() { |
- if (!isPromoAvailable()) return; |
+ public void createSearchPromo() { |
+ if (!isPanelPromoAvailable()) return; |
assert mContainerView != null; |
- if (mPromoView == null) { |
+ if (mSearchPromoView == null) { |
LayoutInflater.from(mContext).inflate( |
R.layout.contextual_search_opt_out_promo, mContainerView); |
- mPromoView = (ContextualSearchOptOutPromo) |
+ mSearchPromoView = (ContextualSearchOptOutPromo) |
mContainerView.findViewById(R.id.contextual_search_opt_out_promo); |
if (mResourceLoader != null) { |
mResourceLoader.registerResource(R.id.contextual_search_opt_out_promo, |
- mPromoView.getResourceAdapter()); |
+ mSearchPromoView.getResourceAdapter()); |
} |
- mPromoView.setPromoHost(this); |
- setPromoContentHeightPx(mPromoView.getHeightForGivenWidth(mContainerView.getWidth())); |
- } |
- |
- assert mPromoView != null; |
+ mSearchPromoView.setPromoHost(this); |
+ setPromoContentHeightPx( |
+ mSearchPromoView.getHeightForGivenWidth(mContainerView.getWidth())); |
+ } |
+ |
+ assert mSearchPromoView != null; |
} |
/** |
* Destroys the Search Promo View. |
*/ |
- protected void destroyPromoView() { |
- if (!isPromoAvailable()) return; |
- |
- if (mPromoView != null) { |
- mContainerView.removeView(mPromoView); |
- mPromoView = null; |
+ protected void destroySearchPromo() { |
+ if (!isPanelPromoAvailable()) return; |
+ |
+ if (mSearchPromoView != null) { |
+ mContainerView.removeView(mSearchPromoView); |
+ mSearchPromoView = null; |
if (mResourceLoader != null) { |
mResourceLoader.unregisterResource(R.id.contextual_search_opt_out_promo); |
} |
@@ -1230,14 +1354,14 @@ |
* @param y The Y position. |
*/ |
public void showPromoViewAtYPosition(float y) { |
- if (mPromoView == null || !isPromoAvailable()) return; |
- |
- mPromoView.setTranslationY(y); |
- mPromoView.setVisibility(View.VISIBLE); |
+ if (mSearchPromoView == null || !isPanelPromoAvailable()) return; |
+ |
+ mSearchPromoView.setTranslationY(y); |
+ mSearchPromoView.setVisibility(View.VISIBLE); |
// NOTE(pedrosimonetti): We need to call requestLayout, otherwise |
// the Promo View will not become visible. |
- mPromoView.requestLayout(); |
+ mSearchPromoView.requestLayout(); |
mIsSearchPromoViewVisible = true; |
} |
@@ -1246,13 +1370,13 @@ |
* Hides the Search Promo View. |
*/ |
public void hidePromoView() { |
- if (mPromoView == null |
+ if (mSearchPromoView == null |
|| !mIsSearchPromoViewVisible |
- || !isPromoAvailable()) { |
+ || !isPanelPromoAvailable()) { |
return; |
} |
- mPromoView.setVisibility(View.INVISIBLE); |
+ mSearchPromoView.setVisibility(View.INVISIBLE); |
mIsSearchPromoViewVisible = false; |
} |
@@ -1266,4 +1390,69 @@ |
updatePromoVisibility(percentage); |
updateSearchBarShadow(); |
} |
+ |
+ // ============================================================================================ |
+ // Opt In Promo |
+ // ============================================================================================ |
+ |
+ /** |
+ * Updates the UI state for a given |height| when performing the opt-in animation. |
+ * |
+ * @param height The Contextual Search Panel height. |
+ */ |
+ protected void setPanelHeightForPromoOptInAnimation(float height) { |
+ PanelState endState = PanelState.EXPANDED; |
+ PanelState startState = PanelState.PROMO; |
+ float percentage = getStateCompletion(height, startState, endState); |
+ |
+ updatePanelSize(height, endState, percentage); |
+ |
+ updatePanelForPromoOptInAnimation(percentage); |
+ } |
+ |
+ /** |
+ * Updates the UI state for the PROMO to EXPANDED transition (and vice versa), |
+ * according to a completion |percentage|. |
+ * |
+ * @param percentage The completion percentage. |
+ */ |
+ private void updatePanelForPromoOptInAnimation(float percentage) { |
+ // Base page offset. |
+ float baseBaseY = MathUtils.interpolate( |
+ getPromoBasePageOffsetY(), |
+ getBasePageTargetY(), |
+ percentage); |
+ mBasePageY = baseBaseY; |
+ |
+ // Base page brightness. |
+ mBasePageBrightness = BASE_PAGE_BRIGHTNESS_STATE_EXPANDED; |
+ |
+ // Search Bar height. |
+ float searchBarHeight = Math.round(MathUtils.interpolate( |
+ mSearchBarHeightPromo, |
+ mSearchBarHeightExpanded, |
+ percentage)); |
+ mSearchBarHeight = searchBarHeight; |
+ |
+ // Search Bar border. |
+ mIsSearchBarBorderVisible = false; |
+ |
+ // Search Bar text opacity. |
+ final float threshold = 0.5f; |
+ float searchBarTextOpacity = MathUtils.interpolate(0.f, 1.f, |
+ Math.max(percentage - threshold, 0) / threshold); |
+ mSearchBarTextOpacity = searchBarTextOpacity; |
+ |
+ // Search provider icon opacity. |
+ boolean shouldDisplaySearchProviderIcon = shouldHidePromoHeader(); |
+ mSearchProviderIconOpacity = shouldDisplaySearchProviderIcon |
+ ? 1.f : MathUtils.interpolate(0.f, 1.f, percentage); |
+ |
+ // Search icon opacity. |
+ mSearchIconOpacity = SEARCH_ICON_OPACITY_PEEKED; |
+ |
+ // Progress Bar. |
+ mProgressBarOpacity = percentage == 1.f ? 1.f : 0.f; |
+ mProgressBarY = searchBarHeight - PROGRESS_BAR_HEIGHT_DP + 1; |
+ } |
} |