Commit 0135e496 authored by David Black's avatar David Black Committed by Commit Bot

Implement DialogPlate motion spec (part 2).

This builds off of DialogPlate motion spec part 1:
https://chromium-review.googlesource.com/c/chromium/src/+/1137843

This CL:
- Fixes issue which caused settings to fade in/out. Previously we used
  two settings buttons, now we use a single button which exists outside
  of the layout containers being animated.
- Implements translation phase of the animation.

See bug for spec/demo.

Bug: b:111500701
Change-Id: I269666dafa815018e0cf65df299aa734eaf80b79
Reviewed-on: https://chromium-review.googlesource.com/1139031
Commit-Queue: David Black <dmblack@google.com>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575901}
parent d8235928
...@@ -40,20 +40,9 @@ constexpr base::TimeDelta kAnimationFadeInDuration = ...@@ -40,20 +40,9 @@ constexpr base::TimeDelta kAnimationFadeInDuration =
base::TimeDelta::FromMilliseconds(100); base::TimeDelta::FromMilliseconds(100);
constexpr base::TimeDelta kAnimationFadeOutDuration = constexpr base::TimeDelta kAnimationFadeOutDuration =
base::TimeDelta::FromMilliseconds(83); base::TimeDelta::FromMilliseconds(83);
constexpr base::TimeDelta kAnimationTransformInDuration =
// Helpers --------------------------------------------------------------------- base::TimeDelta::FromMilliseconds(333);
constexpr int kAnimationTranslationDip = 30;
// Creates a settings button. Caller takes ownership.
views::ImageButton* CreateSettingsButton(DialogPlate* dialog_plate) {
views::ImageButton* settings_button = new views::ImageButton(dialog_plate);
settings_button->set_id(static_cast<int>(DialogPlateButtonId::kSettings));
settings_button->SetImage(
views::Button::ButtonState::STATE_NORMAL,
gfx::CreateVectorIcon(kNotificationSettingsIcon, kIconSizeDip,
gfx::kGoogleGrey600));
settings_button->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip));
return settings_button;
}
} // namespace } // namespace
...@@ -100,10 +89,37 @@ void DialogPlate::ChildVisibilityChanged(views::View* child) { ...@@ -100,10 +89,37 @@ void DialogPlate::ChildVisibilityChanged(views::View* child) {
void DialogPlate::InitLayout() { void DialogPlate::InitLayout() {
SetBackground(views::CreateSolidBackground(SK_ColorWHITE)); SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
SetLayoutManager(std::make_unique<views::FillLayout>());
InitKeyboardLayoutContainer(); views::BoxLayout* layout_manager =
InitVoiceLayoutContainer(); SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(0, 0, 0, kPaddingDip)));
layout_manager->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER);
// Input modality layout container.
views::View* input_modality_layout_container = new views::View();
input_modality_layout_container->SetLayoutManager(
std::make_unique<views::FillLayout>());
input_modality_layout_container->SetPaintToLayer();
input_modality_layout_container->layer()->SetMasksToBounds(true);
InitKeyboardLayoutContainer(input_modality_layout_container);
InitVoiceLayoutContainer(input_modality_layout_container);
layout_manager->SetFlexForView(input_modality_layout_container, 1);
AddChildView(input_modality_layout_container);
// Settings.
views::ImageButton* settings_button = new views::ImageButton(this);
settings_button->set_id(static_cast<int>(DialogPlateButtonId::kSettings));
settings_button->SetImage(
views::Button::ButtonState::STATE_NORMAL,
gfx::CreateVectorIcon(kNotificationSettingsIcon, kIconSizeDip,
gfx::kGoogleGrey600));
settings_button->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip));
AddChildView(settings_button);
// Artificially trigger event to set initial state. // Artificially trigger event to set initial state.
OnInputModalityChanged(assistant_controller_->interaction_controller() OnInputModalityChanged(assistant_controller_->interaction_controller()
...@@ -111,10 +127,12 @@ void DialogPlate::InitLayout() { ...@@ -111,10 +127,12 @@ void DialogPlate::InitLayout() {
->input_modality()); ->input_modality());
} }
void DialogPlate::InitKeyboardLayoutContainer() { void DialogPlate::InitKeyboardLayoutContainer(
views::View* input_modality_layout_container) {
keyboard_layout_container_ = new views::View(); keyboard_layout_container_ = new views::View();
keyboard_layout_container_->SetPaintToLayer(); keyboard_layout_container_->SetPaintToLayer();
keyboard_layout_container_->layer()->SetFillsBoundsOpaquely(false); keyboard_layout_container_->layer()->SetFillsBoundsOpaquely(false);
keyboard_layout_container_->layer()->SetOpacity(0.f);
views::BoxLayout* layout_manager = views::BoxLayout* layout_manager =
keyboard_layout_container_->SetLayoutManager( keyboard_layout_container_->SetLayoutManager(
...@@ -144,48 +162,42 @@ void DialogPlate::InitKeyboardLayoutContainer() { ...@@ -144,48 +162,42 @@ void DialogPlate::InitKeyboardLayoutContainer() {
layout_manager->SetFlexForView(textfield_, 1); layout_manager->SetFlexForView(textfield_, 1);
// Voice input toggle. // Voice input toggle.
voice_input_toggle_ = new views::ImageButton(this); views::ImageButton* voice_input_toggle = new views::ImageButton(this);
voice_input_toggle_->set_id( voice_input_toggle->set_id(
static_cast<int>(DialogPlateButtonId::kVoiceInputToggle)); static_cast<int>(DialogPlateButtonId::kVoiceInputToggle));
voice_input_toggle_->SetImage(views::Button::ButtonState::STATE_NORMAL, voice_input_toggle->SetImage(views::Button::ButtonState::STATE_NORMAL,
gfx::CreateVectorIcon(kMicIcon, kIconSizeDip)); gfx::CreateVectorIcon(kMicIcon, kIconSizeDip));
voice_input_toggle_->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip)); voice_input_toggle->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip));
keyboard_layout_container_->AddChildView(voice_input_toggle_); keyboard_layout_container_->AddChildView(voice_input_toggle);
// Spacer.
views::View* spacer = new views::View();
spacer->SetPreferredSize(gfx::Size(kSpacingDip, kSpacingDip));
keyboard_layout_container_->AddChildView(spacer);
// Settings.
keyboard_layout_container_->AddChildView(CreateSettingsButton(this));
AddChildView(keyboard_layout_container_); input_modality_layout_container->AddChildView(keyboard_layout_container_);
} }
void DialogPlate::InitVoiceLayoutContainer() { void DialogPlate::InitVoiceLayoutContainer(
views::View* input_modality_layout_container) {
voice_layout_container_ = new views::View(); voice_layout_container_ = new views::View();
voice_layout_container_->SetPaintToLayer(); voice_layout_container_->SetPaintToLayer();
voice_layout_container_->layer()->SetFillsBoundsOpaquely(false); voice_layout_container_->layer()->SetFillsBoundsOpaquely(false);
voice_layout_container_->layer()->SetOpacity(0.f);
views::BoxLayout* layout_manager = voice_layout_container_->SetLayoutManager( views::BoxLayout* layout_manager = voice_layout_container_->SetLayoutManager(
std::make_unique<views::BoxLayout>( std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(0, kPaddingDip))); gfx::Insets(0, kPaddingDip, 0, 0)));
layout_manager->set_cross_axis_alignment( layout_manager->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER); views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER);
// Keyboard input toggle. // Keyboard input toggle.
keyboard_input_toggle_ = new views::ImageButton(this); views::ImageButton* keyboard_input_toggle = new views::ImageButton(this);
keyboard_input_toggle_->set_id( keyboard_input_toggle->set_id(
static_cast<int>(DialogPlateButtonId::kKeyboardInputToggle)); static_cast<int>(DialogPlateButtonId::kKeyboardInputToggle));
keyboard_input_toggle_->SetImage( keyboard_input_toggle->SetImage(
views::Button::ButtonState::STATE_NORMAL, views::Button::ButtonState::STATE_NORMAL,
gfx::CreateVectorIcon(kKeyboardIcon, kIconSizeDip, gfx::kGoogleGrey600)); gfx::CreateVectorIcon(kKeyboardIcon, kIconSizeDip, gfx::kGoogleGrey600));
keyboard_input_toggle_->SetPreferredSize( keyboard_input_toggle->SetPreferredSize(
gfx::Size(kIconSizeDip, kIconSizeDip)); gfx::Size(kIconSizeDip, kIconSizeDip));
voice_layout_container_->AddChildView(keyboard_input_toggle_); voice_layout_container_->AddChildView(keyboard_input_toggle);
// Spacer. // Spacer.
views::View* spacer = new views::View(); views::View* spacer = new views::View();
...@@ -203,10 +215,7 @@ void DialogPlate::InitVoiceLayoutContainer() { ...@@ -203,10 +215,7 @@ void DialogPlate::InitVoiceLayoutContainer() {
layout_manager->SetFlexForView(spacer, 1); layout_manager->SetFlexForView(spacer, 1);
// Settings. input_modality_layout_container->AddChildView(voice_layout_container_);
voice_layout_container_->AddChildView(CreateSettingsButton(this));
AddChildView(voice_layout_container_);
} }
void DialogPlate::OnActionPressed() { void DialogPlate::OnActionPressed() {
...@@ -226,37 +235,67 @@ void DialogPlate::OnButtonPressed(DialogPlateButtonId id) { ...@@ -226,37 +235,67 @@ void DialogPlate::OnButtonPressed(DialogPlateButtonId id) {
void DialogPlate::OnInputModalityChanged(InputModality input_modality) { void DialogPlate::OnInputModalityChanged(InputModality input_modality) {
switch (input_modality) { switch (input_modality) {
case InputModality::kKeyboard: case InputModality::kKeyboard: {
// Animate voice layout container opacity to 0%. // Animate voice layout container opacity to 0%.
voice_layout_container_->layer()->GetAnimator()->StartAnimation( voice_layout_container_->layer()->GetAnimator()->StartAnimation(
assistant::util::CreateLayerAnimationSequence( assistant::util::CreateLayerAnimationSequence(
ui::LayerAnimationElement::CreateOpacityElement( assistant::util::CreateOpacityElement(
0.f, kAnimationFadeOutDuration))); 0.f, kAnimationFadeOutDuration,
gfx::Tween::Type::FAST_OUT_LINEAR_IN)));
// Animate keyboard layout container opacity to 100% with delay.
keyboard_layout_container_->layer()->GetAnimator()->StartAnimation( // Apply a pre-transformation on the keyboard layout container so that it
// can be animated into place.
gfx::Transform transform;
transform.Translate(-kAnimationTranslationDip, 0);
keyboard_layout_container_->layer()->SetTransform(transform);
// Animate keyboard layout container.
keyboard_layout_container_->layer()->GetAnimator()->StartTogether(
{// Animate transformation.
assistant::util::CreateLayerAnimationSequence(
assistant::util::CreateTransformElement(
gfx::Transform(), kAnimationTransformInDuration,
gfx::Tween::Type::FAST_OUT_SLOW_IN_2)),
// Animate opacity to 100% with delay.
assistant::util::CreateLayerAnimationSequenceWithDelay( assistant::util::CreateLayerAnimationSequenceWithDelay(
ui::LayerAnimationElement::CreateOpacityElement( assistant::util::CreateOpacityElement(
1.f, kAnimationFadeInDuration), 1.f, kAnimationFadeInDuration,
/*delay=*/kAnimationFadeOutDuration)); gfx::Tween::Type::FAST_OUT_LINEAR_IN),
/*delay=*/kAnimationFadeOutDuration)});
// When switching to keyboard input modality, we focus the textfield. // When switching to keyboard input modality, we focus the textfield.
textfield_->RequestFocus(); textfield_->RequestFocus();
break; break;
case InputModality::kVoice: }
case InputModality::kVoice: {
// Animate keyboard layout container opacity to 0%. // Animate keyboard layout container opacity to 0%.
keyboard_layout_container_->layer()->GetAnimator()->StartAnimation( keyboard_layout_container_->layer()->GetAnimator()->StartAnimation(
assistant::util::CreateLayerAnimationSequence( assistant::util::CreateLayerAnimationSequence(
ui::LayerAnimationElement::CreateOpacityElement( assistant::util::CreateOpacityElement(
0.f, kAnimationFadeOutDuration))); 0.f, kAnimationFadeOutDuration,
gfx::Tween::Type::FAST_OUT_LINEAR_IN)));
// Animate voice layout container opacity to 100% with delay;
voice_layout_container_->layer()->GetAnimator()->StartAnimation( // Apply a pre-transformation on the voice layout container so that it can
// be animated into place.
gfx::Transform transform;
transform.Translate(kAnimationTranslationDip, 0);
voice_layout_container_->layer()->SetTransform(transform);
// Animate voice layout container.
voice_layout_container_->layer()->GetAnimator()->StartTogether(
{// Animate transformation.
assistant::util::CreateLayerAnimationSequence(
assistant::util::CreateTransformElement(
gfx::Transform(), kAnimationTransformInDuration,
gfx::Tween::Type::FAST_OUT_SLOW_IN_2)),
// Animate opacity to 100% with delay.
assistant::util::CreateLayerAnimationSequenceWithDelay( assistant::util::CreateLayerAnimationSequenceWithDelay(
ui::LayerAnimationElement::CreateOpacityElement( assistant::util::CreateOpacityElement(
1.f, kAnimationFadeInDuration), 1.f, kAnimationFadeInDuration,
/*delay=*/kAnimationFadeOutDuration)); gfx::Tween::Type::FAST_OUT_LINEAR_IN),
/*delay=*/kAnimationFadeOutDuration)});
break; break;
}
case InputModality::kStylus: case InputModality::kStylus:
// No action necessary. // No action necessary.
break; break;
......
...@@ -16,10 +16,6 @@ ...@@ -16,10 +16,6 @@
#include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/view.h" #include "ui/views/view.h"
namespace views {
class ImageButton;
} // namespace views
namespace ash { namespace ash {
class AssistantController; class AssistantController;
...@@ -92,18 +88,17 @@ class DialogPlate : public views::View, ...@@ -92,18 +88,17 @@ class DialogPlate : public views::View,
private: private:
void InitLayout(); void InitLayout();
void InitKeyboardLayoutContainer(); void InitKeyboardLayoutContainer(
void InitVoiceLayoutContainer(); views::View* input_modality_layout_container);
void InitVoiceLayoutContainer(views::View* input_modality_layout_container);
void OnButtonPressed(DialogPlateButtonId id); void OnButtonPressed(DialogPlateButtonId id);
AssistantController* const assistant_controller_; // Owned by Shell. AssistantController* const assistant_controller_; // Owned by Shell.
views::ImageButton* keyboard_input_toggle_; // Owned by view hierarchy.
views::View* keyboard_layout_container_; // Owned by view hierarchy. views::View* keyboard_layout_container_; // Owned by view hierarchy.
views::Textfield* textfield_; // Owned by view hierarchy.
views::ImageButton* voice_input_toggle_; // Owned by view hierarchy.
views::View* voice_layout_container_; // Owned by view hierarchy. views::View* voice_layout_container_; // Owned by view hierarchy.
views::Textfield* textfield_; // Owned by view hierarchy.
base::ObserverList<DialogPlateObserver> observers_; base::ObserverList<DialogPlateObserver> observers_;
......
...@@ -13,15 +13,22 @@ namespace assistant { ...@@ -13,15 +13,22 @@ namespace assistant {
namespace util { namespace util {
ui::LayerAnimationSequence* CreateLayerAnimationSequence( ui::LayerAnimationSequence* CreateLayerAnimationSequence(
std::unique_ptr<ui::LayerAnimationElement> layer_animation_element) { std::unique_ptr<ui::LayerAnimationElement> a,
return CreateLayerAnimationSequenceWithDelay( std::unique_ptr<ui::LayerAnimationElement> b) {
std::move(layer_animation_element), ui::LayerAnimationSequence* layer_animation_sequence =
/*delay=*/base::TimeDelta()); new ui::LayerAnimationSequence();
layer_animation_sequence->AddElement(std::move(a));
if (b)
layer_animation_sequence->AddElement(std::move(b));
return layer_animation_sequence;
} }
ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay( ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay(
std::unique_ptr<ui::LayerAnimationElement> layer_animation_element, std::unique_ptr<ui::LayerAnimationElement> layer_animation_element,
base::TimeDelta delay) { const base::TimeDelta& delay) {
DCHECK(delay.InMilliseconds() >= 0); DCHECK(delay.InMilliseconds() >= 0);
ui::LayerAnimationSequence* layer_animation_sequence = ui::LayerAnimationSequence* layer_animation_sequence =
...@@ -38,6 +45,26 @@ ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay( ...@@ -38,6 +45,26 @@ ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay(
return layer_animation_sequence; return layer_animation_sequence;
} }
std::unique_ptr<ui::LayerAnimationElement> CreateOpacityElement(
float opacity,
const base::TimeDelta& duration,
const gfx::Tween::Type& tween) {
std::unique_ptr<ui::LayerAnimationElement> layer_animation_element =
ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
layer_animation_element->set_tween_type(tween);
return layer_animation_element;
}
std::unique_ptr<ui::LayerAnimationElement> CreateTransformElement(
const gfx::Transform& transform,
const base::TimeDelta& duration,
const gfx::Tween::Type& tween) {
std::unique_ptr<ui::LayerAnimationElement> layer_animation_element =
ui::LayerAnimationElement::CreateTransformElement(transform, duration);
layer_animation_element->set_tween_type(tween);
return layer_animation_element;
}
} // namespace util } // namespace util
} // namespace assistant } // namespace assistant
} // namespace ash } // namespace ash
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <memory> #include <memory>
#include "ui/gfx/animation/tween.h"
namespace base { namespace base {
class TimeDelta; class TimeDelta;
} // namespace base } // namespace base
...@@ -21,17 +23,31 @@ namespace assistant { ...@@ -21,17 +23,31 @@ namespace assistant {
namespace util { namespace util {
// Creates a LayerAnimationSequence containing the specified // Creates a LayerAnimationSequence containing the specified
// |layer_animation_element|. The method caller assumes ownership of the // LayerAnimationElements. The method caller assumes ownership of the
// returned pointer. // returned pointer.
ui::LayerAnimationSequence* CreateLayerAnimationSequence( ui::LayerAnimationSequence* CreateLayerAnimationSequence(
std::unique_ptr<ui::LayerAnimationElement> layer_animation_element); std::unique_ptr<ui::LayerAnimationElement> a,
std::unique_ptr<ui::LayerAnimationElement> b = nullptr);
// Creates a LayerAnimationSequence containing the specified // Creates a LayerAnimationSequence containing the specified
// |layer_animation_element| to be started after the given |delay|. The method // |layer_animation_element| to be started after the given |delay|. The method
// caller assumes ownership of the returned pointer. // caller assumes ownership of the returned pointer.
ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay( ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay(
std::unique_ptr<ui::LayerAnimationElement> layer_animation_element, std::unique_ptr<ui::LayerAnimationElement> layer_animation_element,
base::TimeDelta delay); const base::TimeDelta& delay);
// Creates a LayerAnimationElement to animate opacity with the given parameters.
std::unique_ptr<ui::LayerAnimationElement> CreateOpacityElement(
float opacity,
const base::TimeDelta& duration,
const gfx::Tween::Type& tween = gfx::Tween::Type::LINEAR);
// Creates a LayerAnimationElement to animate transform with the given
// parameters.
std::unique_ptr<ui::LayerAnimationElement> CreateTransformElement(
const gfx::Transform& transform,
const base::TimeDelta& duration,
const gfx::Tween::Type& tween = gfx::Tween::Type::LINEAR);
} // namespace util } // namespace util
} // namespace assistant } // namespace assistant
......
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