Commit e0d1ef57 authored by Jun Mukai's avatar Jun Mukai Committed by Commit Bot

Use ui::LayerAnimator for app-list folder-related animation

- The folder-view's expansion / shrink can be fully done through
  ui::LayerAnimator since it can animate all of the properties.
- Item view can update the rounded corner and insets with animation
  on folder-item.

It still has a slide-animation in item_view for the indicator
circle of the non-folder items. I believe this can be done through
the ui::LayerAnimator though it would need some amount of refactoring
while it won't affect the performance so much; so this CL leaves
it as-is.

Bug: 983308
Test: manually
Change-Id: Ib954280e3c72fd7c1add1b863349d4793059e14d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1710048
Commit-Queue: Jun Mukai <mukai@chromium.org>
Reviewed-by: default avatarAlex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680065}
parent c3b7c517
......@@ -64,20 +64,14 @@ int GetCompositorActivatedFrameCount(ui::Compositor* compositor) {
// folder's background when opening the folder. Transit the other way when
// closing the folder.
class BackgroundAnimation : public AppListFolderView::Animation,
public views::AnimationDelegateViews {
public ui::ImplicitAnimationObserver {
public:
BackgroundAnimation(bool show,
AppListFolderView* folder_view,
views::View* background_view)
: AnimationDelegateViews(background_view),
show_(show),
animation_(this),
: show_(show),
folder_view_(folder_view),
background_view_(background_view) {
animation_.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
animation_.SetSlideDuration(
AppListConfig::instance().folder_transition_in_duration_ms());
}
background_view_(background_view) {}
~BackgroundAnimation() override = default;
......@@ -88,14 +82,14 @@ class BackgroundAnimation : public AppListFolderView::Animation,
const int icon_radius = AppListConfig::instance().folder_icon_radius();
const int folder_radius =
AppListConfig::instance().folder_background_radius();
from_radius_ = show_ ? icon_radius : folder_radius;
to_radius_ = show_ ? folder_radius : icon_radius;
from_rect_ = show_ ? folder_view_->folder_item_icon_bounds()
: background_view_->bounds();
from_rect_ -= background_view_->bounds().OffsetFromOrigin();
to_rect_ = show_ ? background_view_->bounds()
: folder_view_->folder_item_icon_bounds();
to_rect_ -= background_view_->bounds().OffsetFromOrigin();
const int from_radius = show_ ? icon_radius : folder_radius;
const int to_radius = show_ ? folder_radius : icon_radius;
gfx::Rect from_rect = show_ ? folder_view_->folder_item_icon_bounds()
: background_view_->bounds();
from_rect -= background_view_->bounds().OffsetFromOrigin();
gfx::Rect to_rect = show_ ? background_view_->bounds()
: folder_view_->folder_item_icon_bounds();
to_rect -= background_view_->bounds().OffsetFromOrigin();
const SkColor background_color =
AppListConfig::instance().folder_background_color();
const SkColor from_color =
......@@ -106,55 +100,36 @@ class BackgroundAnimation : public AppListFolderView::Animation,
: AppListConfig::instance().folder_bubble_color();
background_view_->layer()->SetColor(from_color);
background_view_->layer()->SetClipRect(from_rect_);
background_view_->layer()->SetClipRect(from_rect);
background_view_->layer()->SetRoundedCornerRadius(
gfx::RoundedCornersF(from_radius_));
gfx::RoundedCornersF(from_radius));
// We use the layer animation for the color, while gfx::Animation to update
// the corner radius and the clip rect. They can be slightly inconsistent
// since these animations run independently.
ui::ScopedLayerAnimationSettings settings(
background_view_->layer()->GetAnimator());
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
AppListConfig::instance().folder_transition_in_duration_ms()));
settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
settings.AddObserver(this);
background_view_->layer()->SetColor(to_color);
animation_.Show();
background_view_->layer()->SetClipRect(to_rect);
background_view_->layer()->SetRoundedCornerRadius(
gfx::RoundedCornersF(to_radius));
is_animating_ = true;
}
bool IsAnimationRunning() override { return animation_.is_animating(); }
bool IsAnimationRunning() override { return is_animating_; }
// gfx::AnimationDelegate
void AnimationProgressed(const gfx::Animation* animation) override {
const double progress = animation->GetCurrentValue();
const int current_radius =
gfx::Tween::IntValueBetween(progress, from_radius_, to_radius_);
background_view_->layer()->SetRoundedCornerRadius(
gfx::RoundedCornersF(current_radius));
const gfx::Rect current_bounds =
gfx::Tween::RectValueBetween(progress, from_rect_, to_rect_);
background_view_->layer()->SetClipRect(current_bounds);
}
void AnimationEnded(const gfx::Animation* animation) override {
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override {
is_animating_ = false;
folder_view_->RecordAnimationSmoothness();
}
void AnimationCanceled(const gfx::Animation* animation) override {
AnimationEnded(animation);
}
// True if opening the folder.
const bool show_;
// The source and target state of the background's corner radius.
int from_radius_ = 0;
int to_radius_ = 0;
bool is_animating_ = false;
// The source and target state of the bounds of the background.
gfx::Rect from_rect_;
gfx::Rect to_rect_;
gfx::SlideAnimation animation_;
AppListFolderView* const folder_view_; // Not owned.
views::View* const background_view_; // Not owned.
......
......@@ -159,6 +159,22 @@ class AppListItemView::IconImageView : public views::ImageView {
return old_layer;
}
// Update the rounded corner and insets with animation. |show| is true when
// the target rounded corner radius and insets are for showing the indicator
// circle.
void AnimateRoundedCornerAndInsets(bool show) {
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
settings.SetTweenType(gfx::Tween::EASE_IN);
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
kDraggedViewHoverAnimationDurationForFolder));
SetRoundedCornerAndInsets(
show ? AppListConfig::instance().folder_unclipped_icon_dimension() / 2
: AppListConfig::instance().folder_icon_dimension() / 2,
show ? gfx::Insets()
: gfx::Insets(AppListConfig::instance().folder_icon_insets()));
}
// Sets the rounded corner and the clip insets.
void SetRoundedCornerAndInsets(int corner_radius, const gfx::Insets& insets) {
EnsureLayer();
......@@ -761,11 +777,19 @@ base::string16 AppListItemView::GetTooltipText(const gfx::Point& p) const {
}
void AppListItemView::OnDraggedViewEnter() {
if (is_folder_) {
icon_->AnimateRoundedCornerAndInsets(true);
return;
}
CreateDraggedViewHoverAnimation();
dragged_view_hover_animation_->Show();
}
void AppListItemView::OnDraggedViewExit() {
if (is_folder_) {
icon_->AnimateRoundedCornerAndInsets(false);
return;
}
CreateDraggedViewHoverAnimation();
dragged_view_hover_animation_->Hide();
}
......@@ -786,18 +810,7 @@ void AppListItemView::EnsureLayer() {
}
void AppListItemView::AnimationProgressed(const gfx::Animation* animation) {
if (is_folder_) {
// Animate the folder icon via changing mask layer's corner radius and
// insets.
const double progress = animation->GetCurrentValue();
const int corner_radius = gfx::Tween::IntValueBetween(
progress, AppListConfig::instance().folder_icon_dimension() / 2,
AppListConfig::instance().folder_unclipped_icon_dimension() / 2);
const int insets = gfx::Tween::IntValueBetween(
progress, AppListConfig::instance().folder_icon_insets(), 0);
icon_->SetRoundedCornerAndInsets(corner_radius, gfx::Insets(insets));
return;
}
DCHECK(!is_folder_);
preview_circle_radius_ = gfx::Tween::IntValueBetween(
animation->GetCurrentValue(), 0,
......@@ -926,14 +939,15 @@ int AppListItemView::GetPreviewCircleRadius() const {
}
void AppListItemView::CreateDraggedViewHoverAnimation() {
DCHECK(!is_folder_);
if (dragged_view_hover_animation_)
return;
dragged_view_hover_animation_ = std::make_unique<gfx::SlideAnimation>(this);
dragged_view_hover_animation_->SetTweenType(gfx::Tween::EASE_IN);
dragged_view_hover_animation_->SetSlideDuration(
is_folder_ ? kDraggedViewHoverAnimationDurationForFolder
: kDraggedViewHoverAnimationDuration);
kDraggedViewHoverAnimationDuration);
}
void AppListItemView::AdaptBoundsForSelectionHighlight(gfx::Rect* bounds) {
......
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