Skip to content

Commit

Permalink
cros: Adding show/hide animation for login bubbles.
Browse files Browse the repository at this point in the history
The animation video could be found in crbug.com/779850 comment#2

Bug: 779850
Change-Id: I065b30062c35950a3522a91a0d01b8af6fba65c4
Reviewed-on: https://chromium-review.googlesource.com/745223
Commit-Queue: Xiaoyin Hu <xiaoyinh@chromium.org>
Reviewed-by: Jacob Dufault <jdufault@chromium.org>
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513936}
  • Loading branch information
Sarah Hu authored and Commit Bot committed Nov 3, 2017
1 parent 1d64d9d commit c04ba38
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 18 deletions.
4 changes: 4 additions & 0 deletions ash/login/ui/login_base_bubble_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ LoginBaseBubbleView::LoginBaseBubbleView(views::View* anchor_view)
set_color(SK_ColorBLACK);
set_can_activate(false);
set_close_on_deactivate(false);

// Layer rendering is needed for animation.
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
}

LoginBaseBubbleView::~LoginBaseBubbleView() = default;
Expand Down
77 changes: 64 additions & 13 deletions ash/login/ui/login_bubble.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "ash/login/ui/login_button.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/font.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/image_view.h"
Expand Down Expand Up @@ -34,6 +36,9 @@ constexpr int kAnchorViewHorizontalSpacingDp = 105;
// Vertical spacing between the anchor view and user menu.
constexpr int kAnchorViewUserMenuVerticalSpacingDp = 4;

// The amount of time for bubble show/hide animation.
constexpr int kBubbleAnimationDurationMs = 300;

views::Label* CreateLabel(const base::string16& message, SkColor color) {
views::Label* label = new views::Label(message, views::style::CONTEXT_LABEL,
views::style::STYLE_PRIMARY);
Expand Down Expand Up @@ -130,7 +135,9 @@ LoginBubble::~LoginBubble() {

void LoginBubble::ShowErrorBubble(views::StyledLabel* label,
views::View* anchor_view) {
DCHECK_EQ(bubble_view_, nullptr);
if (bubble_view_)
CloseImmediately();

bubble_view_ = new LoginErrorBubbleView(label, anchor_view);
Show();
}
Expand All @@ -140,7 +147,9 @@ void LoginBubble::ShowUserMenu(const base::string16& message,
views::View* anchor_view,
LoginButton* bubble_opener,
bool show_remove_user) {
DCHECK_EQ(bubble_view_, nullptr);
if (bubble_view_)
CloseImmediately();

bubble_opener_ = bubble_opener;
bubble_view_ = new LoginUserMenuView(message, sub_message, anchor_view,
show_remove_user);
Expand All @@ -150,19 +159,14 @@ void LoginBubble::ShowUserMenu(const base::string16& message,
void LoginBubble::ShowTooltip(const base::string16& message,
views::View* anchor_view) {
if (bubble_view_)
Close();
CloseImmediately();

bubble_view_ = new LoginTooltipView(message, anchor_view);
Show();
}

void LoginBubble::Close() {
if (bubble_opener_)
bubble_opener_->AnimateInkDrop(views::InkDropState::DEACTIVATED,
nullptr /*event*/);

if (bubble_view_)
bubble_view_->GetWidget()->Close();
ScheduleAnimation(false /*visible*/);
}

bool LoginBubble::IsVisible() {
Expand All @@ -171,8 +175,8 @@ bool LoginBubble::IsVisible() {

void LoginBubble::OnWidgetClosing(views::Widget* widget) {
bubble_opener_ = nullptr;
widget->RemoveObserver(this);
bubble_view_ = nullptr;
widget->RemoveObserver(this);
}

void LoginBubble::OnWidgetDestroying(views::Widget* widget) {
Expand Down Expand Up @@ -203,15 +207,29 @@ void LoginBubble::OnKeyEvent(ui::KeyEvent* event) {
Close();
}

void LoginBubble::OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) {
if (!bubble_view_)
return;

bubble_view_->layer()->GetAnimator()->RemoveObserver(this);
if (!is_visible_)
bubble_view_->GetWidget()->Close();
}

void LoginBubble::Show() {
DCHECK(bubble_view_);
views::BubbleDialogDelegateView::CreateBubble(bubble_view_)->Show();
bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
bubble_view_->GetWidget()->AddObserver(this);

if (bubble_opener_)
bubble_opener_->AnimateInkDrop(views::InkDropState::ACTIVATED,
nullptr /*event*/);
ScheduleAnimation(true /*visible*/);
}

void LoginBubble::CloseImmediately() {
DCHECK(bubble_view_);
bubble_view_->layer()->GetAnimator()->RemoveObserver(this);
bubble_view_->GetWidget()->Close();
is_visible_ = false;
}

void LoginBubble::ProcessPressedEvent(const ui::LocatedEvent* event) {
Expand All @@ -237,4 +255,37 @@ void LoginBubble::ProcessPressedEvent(const ui::LocatedEvent* event) {
Close();
}

void LoginBubble::ScheduleAnimation(bool visible) {
if (!bubble_view_ || is_visible_ == visible)
return;

if (bubble_opener_) {
bubble_opener_->AnimateInkDrop(visible ? views::InkDropState::ACTIVATED
: views::InkDropState::DEACTIVATED,
nullptr /*event*/);
}

ui::Layer* layer = bubble_view_->layer();
layer->GetAnimator()->StopAnimating();
is_visible_ = visible;

float opacity_start = 0.0f;
float opacity_end = 1.0f;
if (!is_visible_)
std::swap(opacity_start, opacity_end);

layer->GetAnimator()->AddObserver(this);
layer->SetOpacity(opacity_start);
{
ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
settings.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kBubbleAnimationDurationMs));
settings.SetTweenType(is_visible_ ? gfx::Tween::EASE_OUT
: gfx::Tween::EASE_IN);
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
layer->SetOpacity(opacity_end);
}
}

} // namespace ash
27 changes: 24 additions & 3 deletions ash/login/ui/login_bubble.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ash/ash_export.h"
#include "ash/login/ui/login_base_bubble_view.h"
#include "base/strings/string16.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget_observer.h"

Expand All @@ -22,7 +23,8 @@ class LoginButton;
// This class observes keyboard events, mouse clicks and touch down events
// and dismisses the bubble accordingly.
class ASH_EXPORT LoginBubble : public views::WidgetObserver,
public ui::EventHandler {
public ui::EventHandler,
public ui::LayerAnimationObserver {
public:
LoginBubble();
~LoginBubble() override;
Expand All @@ -45,7 +47,8 @@ class ASH_EXPORT LoginBubble : public views::WidgetObserver,
// Shows a tooltip.
void ShowTooltip(const base::string16& message, views::View* anchor_view);

// Close the bubble.
// Schedule animation for closing the bubble.
// The bubble widget will be closed when the animation is ended.
void Close();

// True if the bubble is visible.
Expand All @@ -60,18 +63,36 @@ class ASH_EXPORT LoginBubble : public views::WidgetObserver,
void OnGestureEvent(ui::GestureEvent* event) override;
void OnKeyEvent(ui::KeyEvent* event) override;

// gfx::LayerAnimationObserver:
void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override{};
void OnLayerAnimationScheduled(
ui::LayerAnimationSequence* sequence) override{};

LoginBaseBubbleView* bubble_view_for_test() { return bubble_view_; }

private:
// Show the bubble with |bubble_view_|.
// Show the bubble widget and schedule animation for bubble showing.
void Show();

// Close the bubble immediately, without scheduling animation.
// Used to clean up old bubble widget when a new bubble is
// going to be created.
void CloseImmediately();

void ProcessPressedEvent(const ui::LocatedEvent* event);

// Starts show/hide animation.
void ScheduleAnimation(bool visible);

LoginBaseBubbleView* bubble_view_ = nullptr;

// A button that could open/close the bubble.
LoginButton* bubble_opener_ = nullptr;

// The status of bubble after animation ends.
bool is_visible_ = false;

DISALLOW_COPY_AND_ASSIGN(LoginBubble);
};

Expand Down
4 changes: 2 additions & 2 deletions ash/login/ui/login_user_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ LoginUserView::LoginUserView(LoginDisplayStyle style,

hover_notifier_ = std::make_unique<HoverNotifier>(
this, base::Bind(&LoginUserView::OnHover, base::Unretained(this)));
user_menu_ = std::make_unique<LoginBubble>();
}

LoginUserView::~LoginUserView() = default;
Expand Down Expand Up @@ -376,8 +377,7 @@ void LoginUserView::ButtonPressed(Button* sender, const ui::Event& event) {
// Handle click on the dropdown arrow.
if (sender == user_dropdown_) {
DCHECK(user_dropdown_);
if (!user_menu_ || !user_menu_->IsVisible()) {
user_menu_ = std::make_unique<LoginBubble>();
if (!user_menu_->IsVisible()) {
base::string16 display_name =
base::UTF8ToUTF16(current_user_->basic_user_info->display_name);

Expand Down

0 comments on commit c04ba38

Please sign in to comment.