Commit a1e1a4b7 authored by Christian Dullweber's avatar Christian Dullweber Committed by Commit Bot

Animate PageInfo subpage transition

Create "fade-through" animation to switch between main page and subpage.
Remove animation for page-info rows.

Video: https://crbug.com/1077766#c42
Bug: 1077766
Change-Id: I330b57b79a0e6dbd421b1d10ac897f16246f2f6b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2418373Reviewed-by: default avatarEhimare Okoyomon <eokoyomon@chromium.org>
Commit-Queue: Christian Dullweber <dullweber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808358}
parent 6d6f83a8
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:ellipsize="end"
android:layout_marginVertical="16dp" android:layout_marginVertical="16dp"
android:ellipsize="end"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
...@@ -33,42 +33,49 @@ ...@@ -33,42 +33,49 @@
android:ellipsize="end" android:ellipsize="end"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
android:paddingVertical="16dp" android:paddingVertical="16dp"
android:visibility="gone"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> android:textAppearance="@style/TextAppearance.TextLarge.Primary"
android:visibility="gone" />
<LinearLayout <LinearLayout
android:id="@+id/page_info_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical">
android:gravity="center_vertical"
android:paddingHorizontal="16dp"
android:id="@+id/page_info_subpage_header">
<org.chromium.ui.widget.ChromeImageButton <LinearLayout
android:id="@+id/subpage_back_button" android:id="@+id/page_info_subpage_header"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="-12dp" android:gravity="center_vertical"
android:minHeight="@dimen/min_touch_target_size" android:orientation="horizontal"
android:minWidth="@dimen/min_touch_target_size" android:paddingHorizontal="16dp">
android:layout_marginEnd="20dp"
android:background="?attr/selectableItemBackgroundBorderless" <org.chromium.ui.widget.ChromeImageButton
android:src="@drawable/ic_arrow_back_white_24dp" android:id="@+id/subpage_back_button"
app:tint="@color/default_icon_color" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-12dp"
android:layout_marginEnd="20dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:minWidth="@dimen/min_touch_target_size"
android:minHeight="@dimen/min_touch_target_size"
android:src="@drawable/ic_arrow_back_white_24dp"
app:tint="@color/default_icon_color" />
<TextView <TextView
android:id="@+id/page_info_subpage_title" android:id="@+id/page_info_subpage_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
</LinearLayout>
<!-- Programmatically add page specific inner view here -->
<FrameLayout
android:id="@+id/page_info_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
android:layout_marginVertical="12dp"
android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
</LinearLayout> </LinearLayout>
<!-- Programmatically add page specific inner view here -->
<FrameLayout
android:id="@+id/page_info_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout> </LinearLayout>
...@@ -8,6 +8,7 @@ import android.content.Context; ...@@ -8,6 +8,7 @@ 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.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.TextView; import android.widget.TextView;
...@@ -17,6 +18,10 @@ import org.chromium.ui.widget.ChromeImageButton; ...@@ -17,6 +18,10 @@ import org.chromium.ui.widget.ChromeImageButton;
* Represents the url, a sub page header and container for page info content. * Represents the url, a sub page header and container for page info content.
*/ */
public class PageInfoContainer extends FrameLayout { public class PageInfoContainer extends FrameLayout {
public static final float sScale = 0.92f;
public static final int sOutDuration = 90;
public static final int sInDuration = 210;
/** Parameters to configure the view of page info subpage. */ /** Parameters to configure the view of page info subpage. */
public static class Params { public static class Params {
// Whether the URL title should be shown. // Whether the URL title should be shown.
...@@ -35,16 +40,20 @@ public class PageInfoContainer extends FrameLayout { ...@@ -35,16 +40,20 @@ public class PageInfoContainer extends FrameLayout {
private PageInfoView.ElidedUrlTextView mUrlTitle; private PageInfoView.ElidedUrlTextView mUrlTitle;
private TextView mTruncatedUrlTitle; private TextView mTruncatedUrlTitle;
private final ViewGroup mWrapper;
private final ViewGroup mContent;
private View mCurrentView;
private final View mSubpageHeader; private final View mSubpageHeader;
private TextView mSubpageTitle; private final TextView mSubpageTitle;
private final FrameLayout mContent;
public PageInfoContainer(Context context) { public PageInfoContainer(Context context) {
super(context); super(context);
LayoutInflater.from(context).inflate(R.layout.page_info_container, this, true); LayoutInflater.from(context).inflate(R.layout.page_info_container, this, true);
mWrapper = findViewById(R.id.page_info_wrapper);
mContent = findViewById(R.id.page_info_content);
mSubpageHeader = findViewById(R.id.page_info_subpage_header); mSubpageHeader = findViewById(R.id.page_info_subpage_header);
mSubpageTitle = findViewById(R.id.page_info_subpage_title); mSubpageTitle = findViewById(R.id.page_info_subpage_title);
mContent = findViewById(R.id.page_info_content);
} }
public void setParams(Params params) { public void setParams(Params params) {
...@@ -94,10 +103,37 @@ public class PageInfoContainer extends FrameLayout { ...@@ -94,10 +103,37 @@ public class PageInfoContainer extends FrameLayout {
mTruncatedUrlTitle.setCompoundDrawablesRelative(favicon, null, null, null); mTruncatedUrlTitle.setCompoundDrawablesRelative(favicon, null, null, null);
} }
public void showPage(View view, CharSequence title, boolean isMainPage) { public void showPage(View view, CharSequence subPageTitle, Runnable onPreviousPageRemoved) {
if (mCurrentView == null) {
// Don't animate if there is no current view.
assert onPreviousPageRemoved == null;
replaceContentView(view, subPageTitle);
return;
}
// Create "fade-through" animation.
// TODO(crbug.com/1077766): Animate height change and set correct interpolator.
mWrapper.animate().setDuration(sOutDuration).alpha(0).withEndAction(() -> {
replaceContentView(view, subPageTitle);
mWrapper.setScaleX(sScale);
mWrapper.setScaleY(sScale);
mWrapper.setAlpha(0);
mWrapper.animate()
.setDuration(sInDuration)
.scaleX(1)
.scaleY(1)
.alpha(1)
.withEndAction(onPreviousPageRemoved);
});
}
/**
* Replaces the current view with |view| and configures the subpage header.
*/
private void replaceContentView(View view, CharSequence subPageTitle) {
mContent.removeAllViews(); mContent.removeAllViews();
mCurrentView = view;
mSubpageHeader.setVisibility(subPageTitle != null ? VISIBLE : GONE);
mSubpageTitle.setText(subPageTitle);
mContent.addView(view); mContent.addView(view);
mSubpageHeader.setVisibility(isMainPage ? GONE : VISIBLE);
mSubpageTitle.setText(title);
} }
} }
...@@ -264,7 +264,7 @@ public class PageInfoController implements PageInfoMainController, ModalDialogPr ...@@ -264,7 +264,7 @@ public class PageInfoController implements PageInfoMainController, ModalDialogPr
containerParams.urlTitleLongClickCallback = viewParams.urlTitleLongClickCallback; containerParams.urlTitleLongClickCallback = viewParams.urlTitleLongClickCallback;
containerParams.urlTitleShown = viewParams.urlTitleShown; containerParams.urlTitleShown = viewParams.urlTitleShown;
mContainer.setParams(containerParams); mContainer.setParams(containerParams);
mContainer.showPage(mView, "", true); mContainer.showPage(mView, null, null);
PageInfoViewV2 view2 = (PageInfoViewV2) mView; PageInfoViewV2 view2 = (PageInfoViewV2) mView;
mConnectionController = new PageInfoConnectionController( mConnectionController = new PageInfoConnectionController(
this, view2.getConnectionRowView(), mWebContents, mDelegate.getVrHandler()); this, view2.getConnectionRowView(), mWebContents, mDelegate.getVrHandler());
...@@ -580,17 +580,23 @@ public class PageInfoController implements PageInfoMainController, ModalDialogPr ...@@ -580,17 +580,23 @@ public class PageInfoController implements PageInfoMainController, ModalDialogPr
*/ */
@Override @Override
public void launchSubpage(PageInfoSubpageController controller) { public void launchSubpage(PageInfoSubpageController controller) {
if (mSubpageController != null) return;
mSubpageController = controller; mSubpageController = controller;
CharSequence title = mSubpageController.getSubpageTitle(); CharSequence title = mSubpageController.getSubpageTitle();
View subview = mSubpageController.createViewForSubpage(mContainer); View subview = mSubpageController.createViewForSubpage(mContainer);
mContainer.showPage(subview, title, false); mContainer.showPage(subview, title, null);
controller.onSubPageAttached(); controller.onSubPageAttached();
} }
/**
* Exits the subpage of the current controller.
*/
@Override @Override
public void exitSubpage() { public void exitSubpage() {
mContainer.showPage(mView, "", true); if (mSubpageController == null) return;
mSubpageController.onSubpageRemoved(); mContainer.showPage(mView, null, () -> {
mSubpageController = null; mSubpageController.onSubpageRemoved();
mSubpageController = null;
});
} }
} }
...@@ -75,7 +75,7 @@ public class PageInfoCookiesController ...@@ -75,7 +75,7 @@ public class PageInfoCookiesController
mSubPage.setParams(params); mSubPage.setParams(params);
AppCompatActivity host = (AppCompatActivity) mRowView.getContext(); AppCompatActivity host = (AppCompatActivity) mRowView.getContext();
host.getSupportFragmentManager().beginTransaction().add(mSubPage, "FOO").commitNow(); host.getSupportFragmentManager().beginTransaction().add(mSubPage, null).commitNow();
return mSubPage.requireView(); return mSubPage.requireView();
} }
...@@ -99,6 +99,7 @@ public class PageInfoCookiesController ...@@ -99,6 +99,7 @@ public class PageInfoCookiesController
@Override @Override
public void onSubpageRemoved() { public void onSubpageRemoved() {
assert mSubPage != null;
AppCompatActivity host = (AppCompatActivity) mRowView.getContext(); AppCompatActivity host = (AppCompatActivity) mRowView.getContext();
host.getSupportFragmentManager().beginTransaction().remove(mSubPage).commitNow(); host.getSupportFragmentManager().beginTransaction().remove(mSubPage).commitNow();
mSubPage = null; mSubPage = null;
......
...@@ -64,6 +64,7 @@ public class PageInfoPermissionsController implements PageInfoSubpageController ...@@ -64,6 +64,7 @@ public class PageInfoPermissionsController implements PageInfoSubpageController
@Override @Override
public void onSubpageRemoved() { public void onSubpageRemoved() {
assert mSubpageFragment != null;
AppCompatActivity host = (AppCompatActivity) mRowView.getContext(); AppCompatActivity host = (AppCompatActivity) mRowView.getContext();
host.getSupportFragmentManager().beginTransaction().remove(mSubpageFragment).commitNow(); host.getSupportFragmentManager().beginTransaction().remove(mSubpageFragment).commitNow();
mSubpageFragment = null; mSubpageFragment = null;
......
...@@ -261,18 +261,17 @@ public class PageInfoView extends FrameLayout implements OnClickListener { ...@@ -261,18 +261,17 @@ public class PageInfoView extends FrameLayout implements OnClickListener {
return true; return true;
}); });
} }
initializePageInfoViewChild( initializePageInfoViewChild(mUrlTitle, params.urlTitleShown, params.urlTitleClickCallback);
mUrlTitle, params.urlTitleShown, 0f, params.urlTitleClickCallback);
} }
protected void initPreview(PageInfoViewParams params) { protected void initPreview(PageInfoViewParams params) {
mPreviewMessage = findViewById(R.id.page_info_preview_message); mPreviewMessage = findViewById(R.id.page_info_preview_message);
mPreviewLoadOriginal = findViewById(R.id.page_info_preview_load_original); mPreviewLoadOriginal = findViewById(R.id.page_info_preview_load_original);
mPreviewSeparator = findViewById(R.id.page_info_preview_separator); mPreviewSeparator = findViewById(R.id.page_info_preview_separator);
initializePageInfoViewChild(mPreviewMessage, params.previewUIShown, 0f, null); initializePageInfoViewChild(mPreviewMessage, params.previewUIShown, null);
initializePageInfoViewChild(mPreviewLoadOriginal, params.previewUIShown, 0f, initializePageInfoViewChild(mPreviewLoadOriginal, params.previewUIShown,
params.previewShowOriginalClickCallback); params.previewShowOriginalClickCallback);
initializePageInfoViewChild(mPreviewSeparator, params.previewSeparatorShown, 0f, null); initializePageInfoViewChild(mPreviewSeparator, params.previewSeparatorShown, null);
mPreviewLoadOriginal.setText(params.previewLoadOriginalMessage); mPreviewLoadOriginal.setText(params.previewLoadOriginalMessage);
} }
...@@ -280,21 +279,21 @@ public class PageInfoView extends FrameLayout implements OnClickListener { ...@@ -280,21 +279,21 @@ public class PageInfoView extends FrameLayout implements OnClickListener {
mConnectionSummary = findViewById(R.id.page_info_connection_summary); mConnectionSummary = findViewById(R.id.page_info_connection_summary);
mConnectionMessage = findViewById(R.id.page_info_connection_message); mConnectionMessage = findViewById(R.id.page_info_connection_message);
// Hide the connection summary until its text is set. // Hide the connection summary until its text is set.
initializePageInfoViewChild(mConnectionSummary, false, 0f, null); initializePageInfoViewChild(mConnectionSummary, false, null);
initializePageInfoViewChild(mConnectionMessage, params.connectionMessageShown, 0f, null); initializePageInfoViewChild(mConnectionMessage, params.connectionMessageShown, null);
} }
protected void initPerformance(PageInfoViewParams params) { protected void initPerformance(PageInfoViewParams params) {
mPerformanceSummary = findViewById(R.id.page_info_performance_summary); mPerformanceSummary = findViewById(R.id.page_info_performance_summary);
mPerformanceMessage = findViewById(R.id.page_info_performance_message); mPerformanceMessage = findViewById(R.id.page_info_performance_message);
initializePageInfoViewChild(mPerformanceSummary, false, 0f, null); initializePageInfoViewChild(mPerformanceSummary, false, null);
initializePageInfoViewChild(mPerformanceMessage, false, 0f, null); initializePageInfoViewChild(mPerformanceMessage, false, null);
} }
protected void initHttpsImageCompression(PageInfoViewParams params) { protected void initHttpsImageCompression(PageInfoViewParams params) {
mHttpsImageCompressionMessage = mHttpsImageCompressionMessage =
findViewById(R.id.page_info_lite_mode_https_image_compression_message); findViewById(R.id.page_info_lite_mode_https_image_compression_message);
initializePageInfoViewChild(mHttpsImageCompressionMessage, false, 0f, null); initializePageInfoViewChild(mHttpsImageCompressionMessage, false, null);
} }
protected void initPermissions(PageInfoViewParams params) { protected void initPermissions(PageInfoViewParams params) {
...@@ -302,35 +301,35 @@ public class PageInfoView extends FrameLayout implements OnClickListener { ...@@ -302,35 +301,35 @@ public class PageInfoView extends FrameLayout implements OnClickListener {
mPermissionsSeparator = findViewById(R.id.page_info_permissions_separator); mPermissionsSeparator = findViewById(R.id.page_info_permissions_separator);
mPermissionsList = findViewById(R.id.page_info_permissions_list); mPermissionsList = findViewById(R.id.page_info_permissions_list);
// Hide the permissions list for sites with no permissions. // Hide the permissions list for sites with no permissions.
initializePageInfoViewChild(mPermissionsTitle, false, 0f, null); initializePageInfoViewChild(mPermissionsTitle, false, null);
initializePageInfoViewChild(mPermissionsSeparator, false, 0f, null); initializePageInfoViewChild(mPermissionsSeparator, false, null);
initializePageInfoViewChild(mPermissionsList, false, 1f, null); initializePageInfoViewChild(mPermissionsList, false, null);
} }
protected void initCookies(PageInfoViewParams params) { protected void initCookies(PageInfoViewParams params) {
mCookieControlsSeparator = findViewById(R.id.page_info_cookie_controls_separator); mCookieControlsSeparator = findViewById(R.id.page_info_cookie_controls_separator);
mCookieControlsView = findViewById(R.id.page_info_cookie_controls_view); mCookieControlsView = findViewById(R.id.page_info_cookie_controls_view);
initializePageInfoViewChild(mCookieControlsSeparator, params.cookieControlsShown, 0f, null); initializePageInfoViewChild(mCookieControlsSeparator, params.cookieControlsShown, null);
initializePageInfoViewChild(mCookieControlsView, params.cookieControlsShown, 0f, null); initializePageInfoViewChild(mCookieControlsView, params.cookieControlsShown, null);
mOnUiClosingCallback = params.onUiClosingCallback; mOnUiClosingCallback = params.onUiClosingCallback;
} }
protected void initInstantApp(PageInfoViewParams params) { protected void initInstantApp(PageInfoViewParams params) {
mInstantAppButton = findViewById(R.id.page_info_instant_app_button); mInstantAppButton = findViewById(R.id.page_info_instant_app_button);
initializePageInfoViewChild(mInstantAppButton, params.instantAppButtonShown, 0f, initializePageInfoViewChild(mInstantAppButton, params.instantAppButtonShown,
params.instantAppButtonClickCallback); params.instantAppButtonClickCallback);
} }
protected void initSiteSettings(PageInfoViewParams params) { protected void initSiteSettings(PageInfoViewParams params) {
mSiteSettingsButton = findViewById(R.id.page_info_site_settings_button); mSiteSettingsButton = findViewById(R.id.page_info_site_settings_button);
initializePageInfoViewChild(mSiteSettingsButton, params.siteSettingsButtonShown, 0f, initializePageInfoViewChild(mSiteSettingsButton, params.siteSettingsButtonShown,
params.siteSettingsButtonClickCallback); params.siteSettingsButtonClickCallback);
} }
protected void initOpenOnline(PageInfoViewParams params) { protected void initOpenOnline(PageInfoViewParams params) {
mOpenOnlineButton = findViewById(R.id.page_info_open_online_button); mOpenOnlineButton = findViewById(R.id.page_info_open_online_button);
// The open online button should not fade in. // The open online button should not fade in.
initializePageInfoViewChild(mOpenOnlineButton, params.openOnlineButtonShown, 1f, initializePageInfoViewChild(mOpenOnlineButton, params.openOnlineButtonShown,
params.openOnlineButtonClickCallback); params.openOnlineButtonClickCallback);
} }
...@@ -411,10 +410,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener { ...@@ -411,10 +410,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener {
clickCallback.run(); clickCallback.run();
} }
protected void initializePageInfoViewChild( protected void initializePageInfoViewChild(View child, boolean shown, Runnable clickCallback) {
View child, boolean shown, float alpha, Runnable clickCallback) {
// Make all subviews transparent until the page info view is faded in.
child.setAlpha(alpha);
child.setVisibility(shown ? View.VISIBLE : View.GONE); child.setVisibility(shown ? View.VISIBLE : View.GONE);
child.setTag(R.id.page_info_click_callback, clickCallback); child.setTag(R.id.page_info_click_callback, clickCallback);
if (clickCallback == null) return; if (clickCallback == null) return;
......
...@@ -9,7 +9,7 @@ import android.view.LayoutInflater; ...@@ -9,7 +9,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
...@@ -32,7 +32,7 @@ public class PageInfoViewV2 extends PageInfoView { ...@@ -32,7 +32,7 @@ public class PageInfoViewV2 extends PageInfoView {
protected void init(PageInfoView.PageInfoViewParams params) { protected void init(PageInfoView.PageInfoViewParams params) {
super.init(params); super.init(params);
mRowWrapper = findViewById(R.id.page_info_row_wrapper); mRowWrapper = findViewById(R.id.page_info_row_wrapper);
initializePageInfoViewChild(mRowWrapper, true, 0f, null); initializePageInfoViewChild(mRowWrapper, true, null);
} }
@Override @Override
...@@ -81,13 +81,8 @@ public class PageInfoViewV2 extends PageInfoView { ...@@ -81,13 +81,8 @@ public class PageInfoViewV2 extends PageInfoView {
throw new RuntimeException(); throw new RuntimeException();
} }
/**
* Create a list of all the views which we want to individually fade in.
*/
@Override @Override
protected List<View> collectAnimatableViews() { protected List<View> collectAnimatableViews() {
// TODO(crbug.com/1077766): Sort and use rows instead of the rowWrapper. return Collections.emptyList();
return Arrays.asList(mPreviewMessage, mPreviewLoadOriginal, mPreviewSeparator,
mInstantAppButton, mRowWrapper, mSiteSettingsButton);
} }
} }
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