Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3204)

Unified Diff: ui/views/animation/ink_drop_animation.cc

Issue 1495753002: Make the material design ripple effect more visible on a quick action (single click or single tap) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Polished for review. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/views/animation/ink_drop_animation.cc
diff --git a/ui/views/animation/ink_drop_animation.cc b/ui/views/animation/ink_drop_animation.cc
index cf0c705e7bad27fba65ab352aadbd408bf7dda73..cc8188b976b7e356f6ea1680e9b7cf16ea77389a 100644
--- a/ui/views/animation/ink_drop_animation.cc
+++ b/ui/views/animation/ink_drop_animation.cc
@@ -14,7 +14,10 @@
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/transform_util.h"
#include "ui/views/animation/ink_drop_animation_observer.h"
#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
@@ -34,19 +37,100 @@ const float kMinimumCircleScale = 0.001f;
const SkColor kInkDropColor = SK_ColorBLACK;
// The opacity of the ink drop when it is visible.
-const float kVisibleOpacity = 0.14f;
+const float kVisibleOpacity = 0.11f;
// The opacity of the ink drop when it is not visible.
const float kHiddenOpacity = 0.0f;
-// Durations for the different InkDropState animations in milliseconds.
-const int kHiddenStateAnimationDurationMs = 1;
-const int kActionPendingStateAnimationDurationMs = 500;
-const int kQuickActionStateAnimationDurationMs = 250;
-const int kSlowActionPendingStateAnimationDurationMs = 500;
-const int kSlowActionStateAnimationDurationMs = 250;
-const int kActivatedStateAnimationDurationMs = 125;
-const int kDeactivatedStateAnimationDurationMs = 250;
+// All the sub animations that are used to animate each of the InkDropStates.
+// These are used to get time durations with
+// GetAnimationDuration(InkDropSubAnimations). Note that in general a sub
+// animation defines the duration for either a transformation animation or an
+// opacity animation but there are some exceptions where an entire InkDropState
+// animation consists of only 1 sub animation and it defines the duration for
+// both the transformation and opacity animations.
+enum InkDropSubAnimations {
+ // HIDDEN sub animations.
+
+ // The HIDDEN sub animation that is fading out to a hidden opacity.
+ HIDDEN_FADE_OUT,
+
+ // The HIDDEN sub animation that transforms the shape to a |small_size_|
+ // circle.
+ HIDDEN_TRANSFORM,
+
+ // ACTION_PENDING sub animations.
+
+ // The ACTION_PENDING sub animation that fades in to the visible opacity.
+ ACTION_PENDING_FADE_IN,
+
+ // The ACTION_PENDING sub animation that transforms the shape to a
+ // |large_size_| circle.
+ ACTION_PENDING_TRANSFORM,
+
+ // QUICK_ACTION sub animations.
+
+ // The QUICK_ACTION sub animation that is fading out to a hidden opacity.
+ QUICK_ACTION_FADE_OUT,
+
+ // The QUICK_ACTION sub animation that transforms the shape to a |large_size_|
+ // circle.
+ QUICK_ACTION_TRANSFORM,
+
+ // SLOW_ACTION_PENDING sub animations.
+
+ // The SLOW_ACTION_PENDING animation has only one sub animation which animates
+ // to a |small_size_| rounded rectangle at visible opacity.
+ SLOW_ACTION_PENDING,
+
+ // SLOW_ACTION sub animations.
+
+ // The SLOW_ACTION sub animation that is fading out to a hidden opacity.
+ SLOW_ACTION_FADE_OUT,
+
+ // The SLOW_ACTION sub animation that transforms the shape to a |large_size_|
+ // rounded rectangle.
+ SLOW_ACTION_TRANSFORM,
+
+ // ACTIVATED sub animations.
+
+ // The ACTIVATED sub animation that transforms the shape to a |large_size_|
+ // circle. This is used when the ink drop is in a HIDDEN state prior to
+ // animating to the ACTIVATED state.
+ ACTIVATED_CIRCLE_TRANSFORM,
+
+ // The ACTIVATED sub animation that transforms the shape to a |small_size_|
+ // rounded rectangle.
+ ACTIVATED_RECT_TRANSFORM,
+
+ // DEACTIVATED sub animations.
+
+ // The DEACTIVATED sub animation that is fading out to a hidden opacity.
+ DEACTIVATED_FADE_OUT,
+
+ // The DEACTIVATED sub animation that transforms the shape to a |large_size_|
+ // rounded rectangle.
+ DEACTIVATED_TRANSFORM,
+};
+
+// Duration constants for InkDropStateSubAnimations. See the
+// InkDropStateSubAnimations enum documentation for more info.
+const int kHiddenFadeOutDurationMs = 150;
+const int kHiddenTransformDurationMs = 200;
+const int kActionPendingFadeInDurationMs = 0;
+const int kActionPendingTransformDurationMs = 160;
+const int kQuickActionFadeOutDurationMs = 150;
+const int kQuickActionTransformDurationMs = 160;
+const int kSlowActionPendingDurationMs = 200;
+const int kSlowActionFadeOutDurationMs = 150;
+const int kSlowActionTransformDurationMs = 200;
+const int kActivatedCircleTransformDurationMs = 200;
+const int kActivatedRectTransformDurationMs = 160;
+const int kDeactivatedFadeOutDurationMs = 150;
+const int kDeactivatedTransformDurationMs = 200;
+
+// The scale factor used to burst the QUICK_ACTION bubble as it fades out.
+const float kQuickActionBurstScale = 1.3f;
// A multiplicative factor used to slow down InkDropState animations.
const int kSlowAnimationDurationFactor = 3;
@@ -61,33 +145,50 @@ bool UseFastAnimations() {
return fast;
}
-// Returns the InkDropState animation duration for the given |state|.
-base::TimeDelta GetAnimationDuration(views::InkDropState state) {
+// Returns the InkDropState sub animation duration for the given |state|.
+base::TimeDelta GetAnimationDuration(InkDropSubAnimations state) {
int duration = 0;
switch (state) {
- case views::InkDropState::HIDDEN:
- duration = kHiddenStateAnimationDurationMs;
+ case HIDDEN_FADE_OUT:
+ duration = kHiddenFadeOutDurationMs;
+ break;
+ case HIDDEN_TRANSFORM:
+ duration = kHiddenTransformDurationMs;
+ break;
+ case ACTION_PENDING_FADE_IN:
+ duration = kActionPendingFadeInDurationMs;
+ break;
+ case ACTION_PENDING_TRANSFORM:
+ duration = kActionPendingTransformDurationMs;
break;
- case views::InkDropState::ACTION_PENDING:
- duration = kActionPendingStateAnimationDurationMs;
+ case QUICK_ACTION_FADE_OUT:
+ duration = kQuickActionFadeOutDurationMs;
break;
- case views::InkDropState::QUICK_ACTION:
- duration = kQuickActionStateAnimationDurationMs;
+ case QUICK_ACTION_TRANSFORM:
+ duration = kQuickActionTransformDurationMs;
break;
- case views::InkDropState::SLOW_ACTION_PENDING:
- duration = kSlowActionPendingStateAnimationDurationMs;
+ case SLOW_ACTION_PENDING:
+ duration = kSlowActionPendingDurationMs;
break;
- case views::InkDropState::SLOW_ACTION:
- duration = kSlowActionStateAnimationDurationMs;
+ case SLOW_ACTION_TRANSFORM:
+ duration = kSlowActionTransformDurationMs;
break;
- case views::InkDropState::ACTIVATED:
- duration = kActivatedStateAnimationDurationMs;
+ case SLOW_ACTION_FADE_OUT:
+ duration = kSlowActionFadeOutDurationMs;
break;
- case views::InkDropState::DEACTIVATED:
- duration = kDeactivatedStateAnimationDurationMs;
+ case ACTIVATED_CIRCLE_TRANSFORM:
+ duration = kActivatedCircleTransformDurationMs;
+ break;
+ case ACTIVATED_RECT_TRANSFORM:
+ duration = kActivatedRectTransformDurationMs;
+ break;
+ case DEACTIVATED_FADE_OUT:
+ duration = kDeactivatedFadeOutDurationMs;
+ break;
+ case DEACTIVATED_TRANSFORM:
+ duration = kDeactivatedTransformDurationMs;
varkha 2016/01/28 20:50:45 Maybe refactor this into a lookup table in future
bruthig 2016/01/28 22:38:00 Done.
break;
}
-
return base::TimeDelta::FromMilliseconds(
(UseFastAnimations() ? 1 : kSlowAnimationDurationFactor) * duration);
}
@@ -181,6 +282,12 @@ void InkDropAnimation::SetCenterPoint(const gfx::Point& center_point) {
root_layer_->SetTransform(transform);
}
+void InkDropAnimation::HideImmediately() {
+ AbortAllAnimations();
+ SetStateToHidden();
+ ink_drop_state_ = InkDropState::HIDDEN;
+}
+
std::string InkDropAnimation::ToLayerName(PaintedShape painted_shape) {
switch (painted_shape) {
case TOP_LEFT_CIRCLE:
@@ -205,96 +312,151 @@ std::string InkDropAnimation::ToLayerName(PaintedShape painted_shape) {
void InkDropAnimation::AnimateToStateInternal(
InkDropState ink_drop_state,
ui::LayerAnimationObserver* animation_observer) {
+ InkDropState previous_ink_drop_state = ink_drop_state_;
ink_drop_state_ = ink_drop_state;
- if (ink_drop_state_ == InkDropState::HIDDEN) {
- // Animating to the HIDDEN state doesn't actually use any
- // LayerAnimationSequences so we need to explicitly abort any running ones
- // so that observers receive an InkDropAnimationEnded() event for the
- // running animation prior to receiving an InkDropAnimationStarted() event
- // for the HIDDEN 'animation'.
- AbortAllAnimations();
- root_layer_->SetVisible(false);
- SetStateToHidden();
- return;
- }
-
InkDropTransforms transforms;
root_layer_->SetVisible(true);
switch (ink_drop_state_) {
case InkDropState::HIDDEN:
- // This case is handled above in a short circuit return.
+ if (GetCurrentOpacity() == kHiddenOpacity) {
+ AbortAllAnimations();
+ break;
+ } else {
+ AnimateToOpacity(kHiddenOpacity, GetAnimationDuration(HIDDEN_FADE_OUT),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ CalculateCircleTransforms(small_size_, &transforms);
+ AnimateToTransforms(
+ transforms, GetAnimationDuration(HIDDEN_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ }
break;
case InkDropState::ACTION_PENDING:
+ DCHECK(previous_ink_drop_state == InkDropState::HIDDEN);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ACTION_PENDING_FADE_IN),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ACTION_PENDING_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
CalculateCircleTransforms(large_size_, &transforms);
- AnimateToTransforms(transforms, kVisibleOpacity,
- GetAnimationDuration(InkDropState::ACTION_PENDING),
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(ACTION_PENDING_TRANSFORM),
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
+ gfx::Tween::EASE_IN_OUT, animation_observer);
break;
- case InkDropState::QUICK_ACTION:
- CalculateCircleTransforms(large_size_, &transforms);
- AnimateToTransforms(transforms, kHiddenOpacity,
- GetAnimationDuration(InkDropState::QUICK_ACTION),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
+ case InkDropState::QUICK_ACTION: {
+ DCHECK(previous_ink_drop_state == InkDropState::HIDDEN ||
+ previous_ink_drop_state == InkDropState::ACTION_PENDING);
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(QUICK_ACTION_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ gfx::Size s = ScaleToRoundedSize(large_size_, kQuickActionBurstScale);
+ CalculateCircleTransforms(s, &transforms);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(QUICK_ACTION_TRANSFORM),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
break;
+ }
case InkDropState::SLOW_ACTION_PENDING:
+ DCHECK(previous_ink_drop_state == InkDropState::ACTION_PENDING);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(SLOW_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
CalculateRectTransforms(small_size_, small_corner_radius_, &transforms);
- AnimateToTransforms(
- transforms, kVisibleOpacity,
- GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
+ AnimateToTransforms(transforms, GetAnimationDuration(SLOW_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
break;
- case InkDropState::SLOW_ACTION:
+ case InkDropState::SLOW_ACTION: {
+ DCHECK(previous_ink_drop_state == InkDropState::SLOW_ACTION_PENDING);
+ base::TimeDelta visible_duration =
+ GetAnimationDuration(SLOW_ACTION_TRANSFORM) -
+ GetAnimationDuration(SLOW_ACTION_FADE_OUT);
+ AnimateToOpacity(kVisibleOpacity, visible_duration,
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(SLOW_ACTION_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
- AnimateToTransforms(transforms, kHiddenOpacity,
- GetAnimationDuration(InkDropState::SLOW_ACTION),
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(SLOW_ACTION_TRANSFORM),
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
+ gfx::Tween::EASE_IN_OUT, animation_observer);
break;
- case InkDropState::ACTIVATED:
+ }
+ case InkDropState::ACTIVATED: {
+ // Animate the opacity so that it cancels any opacity animations already
+ // in progress.
+ AnimateToOpacity(kVisibleOpacity, base::TimeDelta(),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+
+ ui::LayerAnimator::PreemptionStrategy rect_transform_preemption_strategy =
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET;
+ if (previous_ink_drop_state == InkDropState::HIDDEN) {
+ rect_transform_preemption_strategy =
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION;
+ CalculateCircleTransforms(large_size_, &transforms);
+ AnimateToTransforms(
+ transforms, GetAnimationDuration(ACTIVATED_CIRCLE_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ } else if (previous_ink_drop_state == InkDropState::ACTION_PENDING) {
+ rect_transform_preemption_strategy =
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION;
+ }
+
CalculateRectTransforms(small_size_, small_corner_radius_, &transforms);
- AnimateToTransforms(transforms, kVisibleOpacity,
- GetAnimationDuration(InkDropState::ACTIVATED),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(ACTIVATED_RECT_TRANSFORM),
+ rect_transform_preemption_strategy,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
break;
- case InkDropState::DEACTIVATED:
+ }
+ case InkDropState::DEACTIVATED: {
+ base::TimeDelta visible_duration =
+ GetAnimationDuration(DEACTIVATED_TRANSFORM) -
+ GetAnimationDuration(DEACTIVATED_FADE_OUT);
+ AnimateToOpacity(kVisibleOpacity, visible_duration,
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(DEACTIVATED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
- AnimateToTransforms(transforms, kHiddenOpacity,
- GetAnimationDuration(InkDropState::DEACTIVATED),
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(DEACTIVATED_TRANSFORM),
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
+ gfx::Tween::EASE_IN_OUT, animation_observer);
break;
+ }
}
}
void InkDropAnimation::AnimateToTransforms(
const InkDropTransforms transforms,
- float opacity,
base::TimeDelta duration,
ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
ui::LayerAnimationObserver* animation_observer) {
- ui::LayerAnimator* root_animator = root_layer_->GetAnimator();
- ui::ScopedLayerAnimationSettings root_animation(root_animator);
- root_animation.SetPreemptionStrategy(preemption_strategy);
- ui::LayerAnimationElement* root_element =
- ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
- ui::LayerAnimationSequence* root_sequence =
- new ui::LayerAnimationSequence(root_element);
-
- if (animation_observer)
- root_sequence->AddObserver(animation_observer);
-
- root_animator->StartAnimation(root_sequence);
-
for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) {
ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator();
ui::ScopedLayerAnimationSettings animation(animator);
animation.SetPreemptionStrategy(preemption_strategy);
+ animation.SetTweenType(tween);
ui::LayerAnimationElement* element =
ui::LayerAnimationElement::CreateTransformElement(transforms[i],
duration);
@@ -314,6 +476,7 @@ void InkDropAnimation::SetStateToHidden() {
CalculateCircleTransforms(gfx::Size(1, 1), &transforms);
SetTransforms(transforms);
SetOpacity(kHiddenOpacity);
+ root_layer_->SetVisible(false);
}
void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) {
@@ -321,10 +484,35 @@ void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) {
painted_layers_[i]->SetTransform(transforms[i]);
}
+float InkDropAnimation::GetCurrentOpacity() const {
+ return root_layer_->opacity();
+}
+
void InkDropAnimation::SetOpacity(float opacity) {
root_layer_->SetOpacity(opacity);
}
+void InkDropAnimation::AnimateToOpacity(
+ float opacity,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* animation_observer) {
+ ui::LayerAnimator* animator = root_layer_->GetAnimator();
+ ui::ScopedLayerAnimationSettings animation_settings(animator);
+ animation_settings.SetPreemptionStrategy(preemption_strategy);
+ animation_settings.SetTweenType(tween);
+ ui::LayerAnimationElement* animation_element =
+ ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
+ ui::LayerAnimationSequence* animation_sequence =
+ new ui::LayerAnimationSequence(animation_element);
+
+ if (animation_observer)
+ animation_sequence->AddObserver(animation_observer);
+
+ animator->StartAnimation(animation_sequence);
+}
+
void InkDropAnimation::CalculateCircleTransforms(
const gfx::Size& size,
InkDropTransforms* transforms_out) const {
@@ -386,10 +574,10 @@ void InkDropAnimation::CalculateRectTransforms(
std::max(kMinimumRectScale, size.height() / rect_delegate_height));
}
-void InkDropAnimation::GetCurrentTansforms(
+void InkDropAnimation::GetCurrentTransforms(
InkDropTransforms* transforms_out) const {
for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- (*transforms_out)[i] = painted_layers_[i]->GetTargetTransform();
+ (*transforms_out)[i] = painted_layers_[i]->transform();
}
void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) {
@@ -440,6 +628,9 @@ void InkDropAnimation::AnimationStartedCallback(
bool InkDropAnimation::AnimationEndedCallback(
InkDropState ink_drop_state,
const ui::CallbackLayerAnimationObserver& observer) {
+ if (ink_drop_state == InkDropState::HIDDEN)
+ SetStateToHidden();
+
FOR_EACH_OBSERVER(
InkDropAnimationObserver, observers_,
InkDropAnimationEnded(ink_drop_state,

Powered by Google App Engine
This is Rietveld 408576698