// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef UI_VIEWS_LAYOUT_ANIMATING_LAYOUT_MANAGER_H_ #define UI_VIEWS_LAYOUT_ANIMATING_LAYOUT_MANAGER_H_ #include <memory> #include <utility> #include <vector> #include "base/memory/raw_ptr.h" #include "base/observer_list.h" #include "base/time/time.h" #include "ui/gfx/animation/tween.h" #include "ui/views/layout/flex_layout_types.h" #include "ui/views/layout/layout_manager_base.h" #include "ui/views/views_export.h" namespace gfx { class AnimationContainer; } // namespace gfx namespace views { // Layout manager which explicitly animates its child views and/or its preferred // size when the target layout changes (the target layout being provided by a // separate, non-animating layout manager; typically a FlexLayout). // // For example, consider a view in which multiple buttons can be displayed // depending on context, in a horizontal row. When we add a button, we want all // the buttons to the left to slide over and the new button to appear in the // gap: // | [a] [b] [c] | // | [a] [b] [c] | // | [a] [b] . [c] | // | [a] [b] .. [c] | // | [a] [b] [x] [c] | // // Without AnimatingLayoutManager you would have to explicitly animate the // bounds of the host view and the layout elements each frame, calculating which // go where. With AnimatingLayout you create a single declarative layout for the // whole thing and just insert the button where you want it. Here's the setup: // // auto* animating_layout = button_container->SetLayoutManager( // std::make_unique<AnimatingLayoutManager>()); // animating_layout->SetBoundsAnimationMode( // AnimatingLayoutManager::BoundsAnimationMode::kAnimateMainAxis); // auto* flex_layout = animating_layout->SetTargetLayoutManager( // std::make_unique<FlexLayout>()); // flex_layout->SetOrientation(LayoutOrientation::kHorizontal) // .SetCollapseMargins(true) // .SetDefault(kMarginsKey, gfx::Insets(5)); // // Now, when you want to add (or remove) a button and animate, you just call: // // button_container->AddChildViewAt(button, position); // button_container->RemoveChildView(button); // // The bounds of |button_container| will then animate appropriately and |button| // will either appear or disappear in the appropriate location. // // Note that under normal operation, any changes made to the host view before // being added to a widget will not result in animation. If initial setup of the // host view happens after being added to a widget, you can call ResetLayout() // to prevent changes made during setup from animating. class VIEWS_EXPORT AnimatingLayoutManager : public LayoutManagerBase { … }; } // namespace views #endif // UI_VIEWS_LAYOUT_ANIMATING_LAYOUT_MANAGER_H_