Commit 5a27872f authored by Dana Fried's avatar Dana Fried Committed by Commit Bot

Add transition animations to views that are fading in or out.

This CL provides expand and contract animations for views that are being
shown or hidden. It should cover the needs of the identity chip and
butter.

Still to do:
 - Move animating_layout_manager to ui/views/layout
 - Rename flex_layout_types_internal to something more appropriate
 - Implement slide and fade animations
 - Handle multiple views being added/removed at once more cleanly
 - Allow per-child-view transition rules instead of a per-layout default

Bug: 1000131
Change-Id: Ia73475e9eda7e72c118a02160b3fc7234474ee83
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1782040Reviewed-by: default avatarCaroline Rising <corising@chromium.org>
Commit-Queue: Dana Fried <dfried@chromium.org>
Auto-Submit: Dana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#693826}
parent 333fcc20
......@@ -66,6 +66,22 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
bool is_animating) = 0;
};
// Describes how a view which is appearing or disappearing during an animation
// behaves. Child views which are removed from the parent view always simply
// disappear; use one of the Fade methods below to cause a view to fade out.
//
// TODO(dfried): break this out into layout_types and make a view class
// property so that it can be set separately on each child view.
enum class FadeInOutMode {
// Default behavior: a view fading in or out is hidden during the animation.
kHide,
// A view fading in or out shrinks to or from nothing.
kScaleFromZero,
// A view fading in or out appears or disappears when it hits its minimum
// size, and scales the rest of the way in or out.
kScaleFromMinimum,
};
// Call QueueDelayedAction() to queue up an action to be performed when the
// current animation ends.
using DelayedAction = base::OnceCallback<void()>;
......@@ -83,6 +99,12 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
gfx::Tween::Type tween_type() const { return tween_type_; }
AnimatingLayoutManager& SetTweenType(gfx::Tween::Type tween_type);
views::LayoutOrientation orientation() const { return orientation_; }
AnimatingLayoutManager& SetOrientation(views::LayoutOrientation orientation);
FadeInOutMode default_fade_mode() const { return default_fade_mode_; }
AnimatingLayoutManager& SetDefaultFadeMode(FadeInOutMode default_fade_mode);
bool is_animating() const { return is_animating_; }
// Sets the owned (non-animating) layout manager which defines the target
......@@ -101,6 +123,16 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
// layout from the embedded layout manager.
void ResetLayout();
// Causes the specified child view to fade out and become hidden. Alternative
// to directly hiding the view (which will have the same effect, but could
// cause visual flicker if the view paints before it can re-layout.
void FadeOut(views::View* child_view);
// Causes the specified child view to fade in and become visible. Alternative
// to directly showing the view (which will have the same effect, but could
// cause visual flicker if the view paints before it can re-layout.
void FadeIn(views::View* child_view);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObserver(Observer* observer) const;
......@@ -140,6 +172,7 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
void OnLayoutChanged() override;
private:
struct LayoutFadeInfo;
class AnimationDelegate;
friend class AnimationDelegate;
......@@ -162,6 +195,14 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
// Runs all delayed actions. See QueueDelayedAction() for more information.
void RunDelayedActions();
// Updates the current layout to |percent| interpolated between the starting
// and target layouts.
void UpdateCurrentLayout(double percent);
// Updates information about which views are fading in or out during the
// current animation.
void CalculateFadeInfos();
// Whether or not to animate the bounds of the host view when the preferred
// size of the layout changes. If false, the size will have to be set
// explicitly by the host view's owner. Bounds animation is done by changing
......@@ -175,6 +216,12 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
// The motion curve of the animation to perform.
gfx::Tween::Type tween_type_ = gfx::Tween::EASE_IN_OUT;
// The layout orientation, used for side and scale fades.
views::LayoutOrientation orientation_ = views::LayoutOrientation::kHorizontal;
// The default fade mode.
FadeInOutMode default_fade_mode_ = FadeInOutMode::kHide;
// Used to determine when to fire animation events.
bool is_animating_ = false;
......@@ -195,6 +242,9 @@ class AnimatingLayoutManager : public views::LayoutManagerBase {
// |current_layout_| will match |target_layout_|.
ProposedLayout target_layout_;
// Stores information about elements fading in or out of the layout.
std::vector<LayoutFadeInfo> fade_infos_;
std::unique_ptr<AnimationDelegate> animation_delegate_;
base::ObserverList<Observer, true> observers_;
std::vector<DelayedAction> delayed_actions_;
......
......@@ -258,28 +258,30 @@ class VIEWS_EXPORT NormalizedRect {
// Normalization and Denormalization -------------------------------------------
NormalizedPoint Normalize(LayoutOrientation orientation,
const gfx::Point& point);
gfx::Point Denormalize(LayoutOrientation orientation,
const NormalizedPoint& point);
NormalizedSize Normalize(LayoutOrientation orientation, const gfx::Size& point);
gfx::Size Denormalize(LayoutOrientation orientation,
const NormalizedSize& point);
NormalizedSizeBounds Normalize(LayoutOrientation orientation,
const SizeBounds& point);
SizeBounds Denormalize(LayoutOrientation orientation,
const NormalizedSizeBounds& point);
NormalizedInsets Normalize(LayoutOrientation orientation,
const gfx::Insets& point);
gfx::Insets Denormalize(LayoutOrientation orientation,
const NormalizedInsets& point);
NormalizedRect Normalize(LayoutOrientation orientation, const gfx::Rect& rect);
gfx::Rect Denormalize(LayoutOrientation orientation,
const NormalizedRect& rect);
NormalizedPoint VIEWS_EXPORT Normalize(LayoutOrientation orientation,
const gfx::Point& point);
gfx::Point VIEWS_EXPORT Denormalize(LayoutOrientation orientation,
const NormalizedPoint& point);
NormalizedSize VIEWS_EXPORT Normalize(LayoutOrientation orientation,
const gfx::Size& point);
gfx::Size VIEWS_EXPORT Denormalize(LayoutOrientation orientation,
const NormalizedSize& point);
NormalizedSizeBounds VIEWS_EXPORT Normalize(LayoutOrientation orientation,
const SizeBounds& point);
SizeBounds VIEWS_EXPORT Denormalize(LayoutOrientation orientation,
const NormalizedSizeBounds& point);
NormalizedInsets VIEWS_EXPORT Normalize(LayoutOrientation orientation,
const gfx::Insets& point);
gfx::Insets VIEWS_EXPORT Denormalize(LayoutOrientation orientation,
const NormalizedInsets& point);
NormalizedRect VIEWS_EXPORT Normalize(LayoutOrientation orientation,
const gfx::Rect& rect);
gfx::Rect VIEWS_EXPORT Denormalize(LayoutOrientation orientation,
const NormalizedRect& rect);
} // namespace internal
} // namespace views
......
......@@ -88,7 +88,6 @@ void LayoutManagerBase::SetChildViewIgnoredByLayout(View* child_view,
DCHECK(it != child_infos_.end());
if (it->second.ignored == ignored)
return;
it->second.ignored = ignored;
base::AutoReset<bool> setter(&suppress_invalidate_, true);
PropagateChildViewIgnoredByLayout(child_view, ignored);
......@@ -104,7 +103,8 @@ bool LayoutManagerBase::IsChildViewIgnoredByLayout(
LayoutManagerBase::LayoutManagerBase() = default;
bool LayoutManagerBase::IsChildIncludedInLayout(const View* child) const {
bool LayoutManagerBase::IsChildIncludedInLayout(const View* child,
bool include_hidden) const {
const auto it = child_infos_.find(child);
// During callbacks when a child is removed we can get in a state where a view
......@@ -113,7 +113,7 @@ bool LayoutManagerBase::IsChildIncludedInLayout(const View* child) const {
if (it == child_infos_.end())
return false;
return !it->second.ignored && it->second.can_be_visible;
return !it->second.ignored && (include_hidden || it->second.can_be_visible);
}
void LayoutManagerBase::ApplyLayout(const ProposedLayout& layout) {
......@@ -266,11 +266,14 @@ LayoutManagerBase* LayoutManagerBase::GetRootLayoutManager() {
bool LayoutManagerBase::PropagateChildViewIgnoredByLayout(View* child_view,
bool ignored) {
bool result = OnChildViewIgnoredByLayout(child_view, ignored);
child_infos_[child_view].ignored = ignored;
bool result = false;
for (auto& owned_layout : owned_layouts_) {
result |=
owned_layout->PropagateChildViewIgnoredByLayout(child_view, ignored);
}
result |= OnChildViewIgnoredByLayout(child_view, ignored);
return result;
}
......
......@@ -125,7 +125,11 @@ class VIEWS_EXPORT LayoutManagerBase : public LayoutManager {
cached_layout_ = layout;
}
bool IsChildIncludedInLayout(const View* child) const;
// Returns true if the specified view is a child of the host view and is not
// ignored. Views hidden by external code are only included if
// |include_hidden| is set.
bool IsChildIncludedInLayout(const View* child,
bool include_hidden = false) const;
// Creates a proposed layout for the host view, including bounds and
// visibility for all children currently included in the layout.
......
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