Commit 6cabcc94 authored by Ahmed Mehfooz's avatar Ahmed Mehfooz Committed by Chromium LUCI CQ

Add bounce animation for tray background views

This CL refactors previous animations for tray background views
to use layer transforms and also adds a new bounce animation
to be used for holding space and screen recorder tray buttons.

Bug: 896739
Change-Id: I29ce064d44eda7ebb3b98f856ba9b2171be0c549
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2589454
Commit-Queue: Ahmed Mehfooz <amehfooz@chromium.org>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837029}
parent 015fd7a9
......@@ -95,6 +95,8 @@ HoldingSpaceTray::HoldingSpaceTray(Shelf* shelf) : TrayBackgroundView(shelf) {
// the holding space model will already have been attached.
if (HoldingSpaceController::Get()->model())
OnHoldingSpaceModelAttached(HoldingSpaceController::Get()->model());
set_use_bounce_in_animation(true);
}
HoldingSpaceTray::~HoldingSpaceTray() = default;
......
......@@ -28,14 +28,18 @@
#include "ash/window_factory.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/scoped_observer.h"
#include "base/time/time.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/interpolated_transform.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/transform.h"
#include "ui/views/accessibility/view_accessibility.h"
......@@ -51,15 +55,23 @@
namespace ash {
namespace {
const int kAnimationDurationForPopupMs = 200;
const int kAnimationDurationForBubblePopupMs = 200;
// Duration of opacity animation for visibility changes.
const int kAnimationDurationForVisibilityMs = 250;
constexpr base::TimeDelta kAnimationDurationForVisibilityMs =
base::TimeDelta::FromMilliseconds(250);
// Bounce animation constants
const base::TimeDelta kAnimationDurationForBounceElement =
base::TimeDelta::FromMilliseconds(250);
const int kAnimationBounceDistance = 16;
const float kAnimationBounceScaleFactor = 0.5;
// When becoming visible delay the animation so that StatusAreaWidgetDelegate
// can animate sibling views out of the position to be occupied by the
// TrayBackgroundView.
const int kShowAnimationDelayMs = 100;
const base::TimeDelta kShowAnimationDelayMs =
base::TimeDelta::FromMilliseconds(100);
// Switches left and right insets if RTL mode is active.
void MirrorInsetsIfNecessary(gfx::Insets* insets) {
......@@ -192,7 +204,6 @@ TrayBackgroundView::TrayBackgroundView(Shelf* shelf)
TrayBackgroundView::~TrayBackgroundView() {
Shell::Get()->system_tray_model()->virtual_keyboard()->RemoveObserver(this);
widget_observer_.reset();
StopObservingImplicitAnimations();
}
void TrayBackgroundView::Initialize() {
......@@ -210,7 +221,8 @@ void TrayBackgroundView::InitializeBubbleAnimations(
window, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
::wm::SetWindowVisibilityAnimationTransition(window, ::wm::ANIMATE_HIDE);
::wm::SetWindowVisibilityAnimationDuration(
window, base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMs));
window,
base::TimeDelta::FromMilliseconds(kAnimationDurationForBubblePopupMs));
}
void TrayBackgroundView::SetVisiblePreferred(bool visible_preferred) {
......@@ -232,13 +244,6 @@ void TrayBackgroundView::StartVisibilityAnimation(bool visible) {
return;
if (visible) {
// The alignment of the shelf can change while the TrayBackgroundView is
// hidden. Reset the offscreen transform so that the animation to becoming
// visible reflects the current layout.
HideTransformation();
// SetVisible(false) is defered until the animation for hiding is done.
// Otherwise the view is immediately hidden and the animation does not
// render.
views::View::SetVisible(true);
// If SetVisible(true) is called while animating to not visible, then
// views::View::SetVisible(true) is a no-op. When the previous animation
......@@ -248,32 +253,13 @@ void TrayBackgroundView::StartVisibilityAnimation(bool visible) {
layer()->SetVisible(true);
}
ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
animation.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kAnimationDurationForVisibilityMs));
animation.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
if (visible) {
animation.SetTweenType(gfx::Tween::EASE_OUT);
// Show is delayed so as to allow time for other children of
// StatusAreaWidget to begin animating to their new positions.
layer()->GetAnimator()->SchedulePauseForProperties(
base::TimeDelta::FromMilliseconds(kShowAnimationDelayMs),
ui::LayerAnimationElement::OPACITY |
ui::LayerAnimationElement::TRANSFORM);
layer()->SetOpacity(1.0f);
gfx::Transform transform;
transform.Translate(0.0f, 0.0f);
layer()->SetTransform(transform);
if (use_bounce_in_animation_)
BounceInAnimation();
else
FadeInAnimation();
} else {
// Listen only to the hide animation. As we cannot turn off visibility
// until the animation is over.
animation.AddObserver(this);
animation.SetTweenType(gfx::Tween::EASE_IN);
layer()->SetOpacity(0.0f);
layer()->SetVisible(false);
HideTransformation();
HideAnimation();
}
}
......@@ -340,6 +326,7 @@ TrayBackgroundView::CreateInkDropHighlight() const {
void TrayBackgroundView::OnVirtualKeyboardVisibilityChanged() {
// We call the base class' SetVisible to skip animations.
if (GetVisible() != GetEffectiveVisibility())
views::View::SetVisible(GetEffectiveVisibility());
}
......@@ -365,7 +352,6 @@ void TrayBackgroundView::UpdateAfterLoginStatusChange() {
}
void TrayBackgroundView::UpdateAfterStatusAreaCollapseChange() {
// We call the base class' SetVisible to skip animations.
views::View::SetVisible(GetEffectiveVisibility());
}
......@@ -382,34 +368,118 @@ void TrayBackgroundView::UpdateBackground() {
layer()->SetClipRect(GetBackgroundBounds());
}
void TrayBackgroundView::OnImplicitAnimationsCompleted() {
// If there is another animation in the queue, the reverse animation was
// triggered before the completion of animating to invisible. Do not turn off
// the visibility so that the next animation may render. The value of
// layer()->GetTargetVisibility() can be incorrect if the hide animation was
// aborted to schedule an animation to become visible. As the new animation
// is not yet added to the queue. crbug.com/374236
if (layer()->GetAnimator()->is_animating() || layer()->GetTargetVisibility())
return;
void TrayBackgroundView::OnLayerAnimationEnded(
ui::LayerAnimationSequence* sequence) {
if (!visible_preferred_)
views::View::SetVisible(false);
else
UpdateBackground();
}
bool TrayBackgroundView::RequiresNotificationWhenAnimatorDestroyed() const {
// This is needed so that OnImplicitAnimationsCompleted() is called even upon
// destruction of the animator. This can occure when parallel animations
// caused by ScreenRotationAnimator end before the animations of
// TrayBackgroundView. This allows for a proper update to the visual state of
// the view. (crbug.com/476667)
return true;
}
void TrayBackgroundView::FadeInAnimation() {
std::unique_ptr<ui::LayerAnimationSequence> fade_sequence =
std::make_unique<ui::LayerAnimationSequence>();
std::unique_ptr<ui::LayerAnimationElement> fade_in =
ui::LayerAnimationElement::CreateOpacityElement(
1.0f, kAnimationDurationForVisibilityMs);
fade_sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
ui::LayerAnimationElement::OPACITY, kShowAnimationDelayMs));
fade_sequence->AddElement(
ui::LayerAnimationElement::CreateOpacityElement(0.0f, base::TimeDelta()));
fade_sequence->AddElement(std::move(fade_in));
void TrayBackgroundView::HideTransformation() {
gfx::Transform transform;
if (shelf_->IsHorizontalAlignment())
transform.Translate(width(), 0.0f);
else
transform.Translate(0.0f, height());
layer()->SetTransform(transform);
std::unique_ptr<ui::LayerAnimationSequence> translate_sequence =
std::make_unique<ui::LayerAnimationSequence>();
translate_sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
ui::LayerAnimationElement::TRANSFORM, kShowAnimationDelayMs));
translate_sequence->AddElement(
ui::LayerAnimationElement::CreateTransformElement(transform,
base::TimeDelta()));
translate_sequence->AddElement(
ui::LayerAnimationElement::CreateTransformElement(
gfx::Transform(), kAnimationDurationForVisibilityMs));
layer()->GetAnimator()->StartTogether(
{fade_sequence.release(), translate_sequence.release()});
}
void TrayBackgroundView::BounceInAnimation() {
layer()->SetColor(color_utils::GetResultingPaintColor(
ShelfConfig::Get()->GetShelfControlButtonColor(),
AshColorProvider::Get()->GetBackgroundColor()));
std::unique_ptr<ui::InterpolatedTransform> scale =
std::make_unique<ui::InterpolatedScale>(
gfx::Point3F(kAnimationBounceScaleFactor, kAnimationBounceScaleFactor,
1),
gfx::Point3F(1, 1, 1));
std::unique_ptr<ui::InterpolatedTransform> scale_about_pivot =
std::make_unique<ui::InterpolatedTransformAboutPivot>(
GetLocalBounds().CenterPoint(), std::move(scale));
scale_about_pivot->SetChild(std::make_unique<ui::InterpolatedTranslation>(
gfx::PointF(0, kAnimationBounceDistance),
gfx::PointF(0, -kAnimationBounceDistance)));
std::unique_ptr<ui::LayerAnimationElement> scale_and_move_up =
ui::LayerAnimationElement::CreateInterpolatedTransformElement(
std::move(scale_about_pivot), kAnimationDurationForBounceElement);
std::unique_ptr<ui::LayerAnimationElement> move_down =
ui::LayerAnimationElement::CreateInterpolatedTransformElement(
std::make_unique<ui::InterpolatedTranslation>(
gfx::PointF(0, -kAnimationBounceDistance),
gfx::PointF(0, kAnimationBounceDistance)),
kAnimationDurationForBounceElement);
move_down->set_tween_type(gfx::Tween::EASE_IN);
std::unique_ptr<ui::LayerAnimationElement> move_up =
ui::LayerAnimationElement::CreateInterpolatedTransformElement(
std::make_unique<ui::InterpolatedTranslation>(
gfx::PointF(0, kAnimationBounceDistance), gfx::PointF(0, 0)),
kAnimationDurationForBounceElement);
std::unique_ptr<ui::LayerAnimationSequence> sequence =
std::make_unique<ui::LayerAnimationSequence>();
sequence->AddElement(
ui::LayerAnimationElement::CreateOpacityElement(1.0, base::TimeDelta()));
sequence->AddElement(std::move(scale_and_move_up));
sequence->AddElement(std::move(move_down));
sequence->AddElement(std::move(move_up));
sequence->AddObserver(this);
layer()->GetAnimator()->StartAnimation(sequence.release());
}
void TrayBackgroundView::HideAnimation() {
std::unique_ptr<ui::LayerAnimationSequence> fade_sequence =
std::make_unique<ui::LayerAnimationSequence>();
std::unique_ptr<ui::LayerAnimationElement> fade_out =
ui::LayerAnimationElement::CreateOpacityElement(
0.0f, kAnimationDurationForVisibilityMs);
fade_sequence->AddElement(std::move(fade_out));
gfx::Transform transform;
if (shelf_->IsHorizontalAlignment())
transform.Translate(width(), 0.0f);
else
transform.Translate(0.0f, height());
std::unique_ptr<ui::LayerAnimationSequence> translate_sequence =
std::make_unique<ui::LayerAnimationSequence>();
translate_sequence->AddElement(
ui::LayerAnimationElement::CreateTransformElement(
transform, kAnimationDurationForVisibilityMs));
fade_sequence->AddObserver(this);
layer()->GetAnimator()->StartTogether(
{fade_sequence.release(), translate_sequence.release()});
}
void TrayBackgroundView::SetIsActive(bool is_active) {
......
......@@ -27,7 +27,7 @@ class TrayEventFilter;
// inherits from ActionableView so that the tray items can override
// PerformAction when clicked on.
class ASH_EXPORT TrayBackgroundView : public ActionableView,
public ui::ImplicitAnimationObserver,
public ui::LayerAnimationObserver,
public ShelfBackgroundAnimatorObserver,
public TrayBubbleView::Delegate,
public VirtualKeyboardModel::Observer {
......@@ -153,6 +153,10 @@ class ASH_EXPORT TrayBackgroundView : public ActionableView,
show_with_virtual_keyboard_ = show_with_virtual_keyboard;
}
void set_use_bounce_in_animation(bool use_bounce_in_animation) {
use_bounce_in_animation_ = use_bounce_in_animation;
}
private:
class TrayWidgetObserver;
......@@ -165,12 +169,16 @@ class ASH_EXPORT TrayBackgroundView : public ActionableView,
const char* GetClassName() const override;
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override;
bool RequiresNotificationWhenAnimatorDestroyed() const override;
void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
void OnLayerAnimationScheduled(
ui::LayerAnimationSequence* sequence) override {}
// Applies transformations to the |layer()| to animate the view when
// SetVisible(false) is called.
void HideTransformation();
void HideAnimation();
void FadeInAnimation();
void BounceInAnimation();
// Helper function that calculates background insets relative to local bounds.
gfx::Insets GetBackgroundInsets() const;
......@@ -204,6 +212,8 @@ class ASH_EXPORT TrayBackgroundView : public ActionableView,
// If true, the view is visible when the status area is collapsed.
bool show_when_collapsed_;
bool use_bounce_in_animation_ = false;
std::unique_ptr<TrayWidgetObserver> widget_observer_;
std::unique_ptr<TrayEventFilter> tray_event_filter_;
......
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