Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: ash/shelf/voice_interaction_overlay.cc

Issue 2972923002: Update voice interaction burst animation (Closed)
Patch Set: fix comments Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/shelf/voice_interaction_overlay.h" 5 #include "ash/shelf/voice_interaction_overlay.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <memory> 8 #include <memory>
9 #include <string>
9 #include <utility> 10 #include <utility>
10 11
11 #include "ash/public/cpp/shelf_types.h" 12 #include "ash/public/cpp/shelf_types.h"
12 #include "ash/resources/vector_icons/vector_icons.h" 13 #include "ash/resources/vector_icons/vector_icons.h"
13 #include "ash/shelf/app_list_button.h" 14 #include "ash/shelf/app_list_button.h"
14 #include "ash/shelf/ink_drop_button_listener.h" 15 #include "ash/shelf/ink_drop_button_listener.h"
15 #include "ash/shelf/shelf.h" 16 #include "ash/shelf/shelf.h"
16 #include "ash/shelf/shelf_constants.h" 17 #include "ash/shelf/shelf_constants.h"
17 #include "ash/shelf/shelf_view.h" 18 #include "ash/shelf/shelf_view.h"
18 #include "ash/shell.h" 19 #include "ash/shell.h"
19 #include "ash/strings/grit/ash_strings.h" 20 #include "ash/strings/grit/ash_strings.h"
20 #include "ash/system/tray/tray_popup_utils.h" 21 #include "ash/system/tray/tray_popup_utils.h"
21 #include "base/command_line.h" 22 #include "base/command_line.h"
22 #include "base/memory/ptr_util.h" 23 #include "base/memory/ptr_util.h"
23 #include "base/metrics/user_metrics.h" 24 #include "base/metrics/user_metrics.h"
24 #include "base/metrics/user_metrics_action.h" 25 #include "base/metrics/user_metrics_action.h"
25 #include "chromeos/chromeos_switches.h" 26 #include "chromeos/chromeos_switches.h"
26 #include "ui/accessibility/ax_node_data.h" 27 #include "ui/accessibility/ax_node_data.h"
27 #include "ui/app_list/presenter/app_list.h" 28 #include "ui/app_list/presenter/app_list.h"
28 #include "ui/base/l10n/l10n_util.h" 29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/compositor/callback_layer_animation_observer.h"
29 #include "ui/compositor/layer_animation_element.h" 31 #include "ui/compositor/layer_animation_element.h"
30 #include "ui/compositor/layer_animation_observer.h" 32 #include "ui/compositor/layer_animation_observer.h"
31 #include "ui/compositor/layer_animation_sequence.h" 33 #include "ui/compositor/layer_animation_sequence.h"
32 #include "ui/compositor/layer_animator.h" 34 #include "ui/compositor/layer_animator.h"
33 #include "ui/compositor/paint_context.h" 35 #include "ui/compositor/paint_context.h"
34 #include "ui/compositor/paint_recorder.h" 36 #include "ui/compositor/paint_recorder.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h" 37 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/gfx/canvas.h" 38 #include "ui/gfx/canvas.h"
37 #include "ui/gfx/image/canvas_image_source.h" 39 #include "ui/gfx/image/canvas_image_source.h"
38 #include "ui/gfx/image/image_skia.h" 40 #include "ui/gfx/image/image_skia.h"
39 #include "ui/gfx/image/image_skia_operations.h" 41 #include "ui/gfx/image/image_skia_operations.h"
40 #include "ui/gfx/paint_vector_icon.h" 42 #include "ui/gfx/paint_vector_icon.h"
41 #include "ui/gfx/scoped_canvas.h" 43 #include "ui/gfx/scoped_canvas.h"
42 #include "ui/gfx/skia_paint_util.h" 44 #include "ui/gfx/skia_paint_util.h"
43 #include "ui/views/animation/flood_fill_ink_drop_ripple.h" 45 #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
44 #include "ui/views/animation/ink_drop_impl.h" 46 #include "ui/views/animation/ink_drop_impl.h"
45 #include "ui/views/animation/ink_drop_mask.h" 47 #include "ui/views/animation/ink_drop_mask.h"
48 #include "ui/views/animation/ink_drop_painted_layer_delegates.h"
46 #include "ui/views/painter.h" 49 #include "ui/views/painter.h"
47 #include "ui/views/widget/widget.h" 50 #include "ui/views/widget/widget.h"
48 51
49 namespace ash { 52 namespace ash {
50 namespace { 53 namespace {
51 constexpr int kFullExpandDurationMs = 450; 54 constexpr int kFullExpandDurationMs = 450;
52 constexpr int kFullRetractDurationMs = 300; 55 constexpr int kFullRetractDurationMs = 300;
53 constexpr int kFullBurstDurationMs = 200; 56 constexpr int kFullBurstDurationMs = 200;
54 57
55 constexpr float kRippleCircleInitRadiusDip = 40.f; 58 constexpr float kRippleCircleInitRadiusDip = 40.f;
56 constexpr float kRippleCircleStartRadiusDip = 1.f; 59 constexpr float kRippleCircleStartRadiusDip = 1.f;
57 constexpr float kRippleCircleRadiusDip = 77.f; 60 constexpr float kRippleCircleRadiusDip = 77.f;
58 constexpr float kRippleCircleBurstRadiusDip = 96.f; 61 constexpr float kRippleCircleBurstRadiusDip = 96.f;
59 constexpr SkColor kRippleColor = SK_ColorWHITE; 62 constexpr SkColor kRippleColor = SK_ColorWHITE;
60 constexpr int kRippleExpandDurationMs = 400; 63 constexpr int kRippleExpandDurationMs = 400;
61 constexpr int kRippleOpacityDurationMs = 100; 64 constexpr int kRippleOpacityDurationMs = 100;
62 constexpr int kRippleOpacityRetractDurationMs = 200; 65 constexpr int kRippleOpacityRetractDurationMs = 200;
63 constexpr float kRippleOpacity = 0.2f; 66 constexpr float kRippleOpacity = 0.2f;
64 67
65 constexpr float kIconInitSizeDip = 24.f; 68 constexpr float kIconInitSizeDip = 48.f;
66 constexpr float kIconStartSizeDip = 4.f; 69 constexpr float kIconStartSizeDip = 4.f;
67 constexpr float kIconSizeDip = 24.f; 70 constexpr float kIconSizeDip = 24.f;
71 constexpr float kIconEndSizeDip = 48.f;
68 constexpr float kIconOffsetDip = 56.f; 72 constexpr float kIconOffsetDip = 56.f;
69 constexpr float kIconOpacity = 1.f; 73 constexpr float kIconOpacity = 1.f;
70 constexpr int kIconBurstDurationMs = 100;
71 74
72 constexpr float kBackgroundInitSizeDip = 48.f; 75 constexpr float kBackgroundInitSizeDip = 48.f;
73 constexpr float kBackgroundStartSizeDip = 10.f; 76 constexpr float kBackgroundStartSizeDip = 10.f;
74 constexpr float kBackgroundSizeDip = 48.f; 77 constexpr float kBackgroundSizeDip = 48.f;
75 constexpr int kBackgroundOpacityDurationMs = 200; 78 constexpr int kBackgroundOpacityDurationMs = 200;
76 constexpr float kBackgroundShadowElevationDip = 24.f; 79 constexpr float kBackgroundShadowElevationDip = 24.f;
80 // TODO(xiaohuic): this is 2x device size, 1x actually have a different size.
81 // Need to figure out a way to dynamically change sizes.
82 constexpr float kBackgroundLargeWidthDip = 352.5f;
83 constexpr float kBackgroundLargeHeightDip = 540.0f;
84 constexpr float kBackgroundCornerRadiusDip = 2.f;
85 constexpr float kBackgroundPaddingDip = 6.f;
86 constexpr int kBackgroundMorphDurationMs = 300;
87
88 constexpr int kHideDurationMs = 200;
89
90 // The minimum scale factor to use when scaling rectangle layers. Smaller values
91 // were causing visual anomalies.
92 constexpr float kMinimumRectScale = 0.0001f;
93
94 // The minimum scale factor to use when scaling circle layers. Smaller values
95 // were causing visual anomalies.
96 constexpr float kMinimumCircleScale = 0.001f;
97
98 class VoiceInteractionIcon : public ui::Layer, public ui::LayerDelegate {
99 public:
100 VoiceInteractionIcon() {
101 set_name("VoiceInteractionOverlay:ICON_LAYER");
102 SetBounds(gfx::Rect(0, 0, kIconInitSizeDip, kIconInitSizeDip));
103 SetFillsBoundsOpaquely(false);
104 SetMasksToBounds(false);
105 set_delegate(this);
106 }
107
108 private:
109 // ui::LayerDelegate:
110 void OnPaintLayer(const ui::PaintContext& context) override {
111 ui::PaintRecorder recorder(context, size());
112 gfx::PaintVectorIcon(recorder.canvas(), kShelfVoiceInteractionIcon,
113 kIconInitSizeDip, 0);
114 }
115
116 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
117
118 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
119
120 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIcon);
121 };
122 } // namespace
77 123
78 class VoiceInteractionIconBackground : public ui::Layer, 124 class VoiceInteractionIconBackground : public ui::Layer,
79 public ui::LayerDelegate { 125 public ui::LayerDelegate {
80 public: 126 public:
81 VoiceInteractionIconBackground() : Layer(ui::LAYER_NOT_DRAWN) { 127 VoiceInteractionIconBackground()
128 : Layer(ui::LAYER_NOT_DRAWN),
129 large_size_(
130 gfx::Size(kBackgroundLargeWidthDip, kBackgroundLargeHeightDip)),
131 small_size_(gfx::Size(kBackgroundSizeDip, kBackgroundSizeDip)),
132 center_point_(
oshima 2017/07/06 22:04:42 I was thinking something like HalfSize(small_siz
xc 2017/07/07 16:38:15 I see, some of the places are getting points, some
133 gfx::PointF(kBackgroundSizeDip / 2, kBackgroundSizeDip / 2)),
134 circle_layer_delegate_(
135 new views::CircleLayerDelegate(SK_ColorWHITE,
136 kBackgroundSizeDip / 2)),
137 rect_layer_delegate_(
138 new views::RectangleLayerDelegate(SK_ColorWHITE,
oshima 2017/07/06 22:04:42 MakeUnique
xc 2017/07/07 16:38:15 Done.
139 gfx::SizeF(small_size_))) {
82 set_name("VoiceInteractionOverlay:BACKGROUND_LAYER"); 140 set_name("VoiceInteractionOverlay:BACKGROUND_LAYER");
83 SetBounds(gfx::Rect(0, 0, kBackgroundInitSizeDip, kBackgroundInitSizeDip)); 141 SetBounds(gfx::Rect(0, 0, kBackgroundInitSizeDip, kBackgroundInitSizeDip));
84 SetFillsBoundsOpaquely(false); 142 SetFillsBoundsOpaquely(false);
85 SetMasksToBounds(false); 143 SetMasksToBounds(false);
86 144
145 for (int i = 0; i < static_cast<int>(PaintedShape::PAINTED_SHAPE_COUNT);
146 ++i)
oshima 2017/07/06 22:04:42 alternatively, you can define const PaintedShape
xc 2017/07/07 16:38:15 Done.
147 AddPaintLayer(static_cast<PaintedShape>(i));
148
87 shadow_values_ = 149 shadow_values_ =
88 gfx::ShadowValue::MakeMdShadowValues(kBackgroundShadowElevationDip); 150 gfx::ShadowValue::MakeMdShadowValues(kBackgroundShadowElevationDip);
89 const gfx::Insets shadow_margin = 151 const gfx::Insets shadow_margin =
90 gfx::ShadowValue::GetMargin(shadow_values_); 152 gfx::ShadowValue::GetMargin(shadow_values_);
91 153
92 shadow_layer_.reset(new ui::Layer()); 154 shadow_layer_.reset(new ui::Layer());
93 shadow_layer_->set_delegate(this); 155 shadow_layer_->set_delegate(this);
94 shadow_layer_->SetFillsBoundsOpaquely(false); 156 shadow_layer_->SetFillsBoundsOpaquely(false);
95 shadow_layer_->SetBounds( 157 shadow_layer_->SetBounds(
96 gfx::Rect(shadow_margin.left(), shadow_margin.top(), 158 gfx::Rect(shadow_margin.left(), shadow_margin.top(),
97 kBackgroundInitSizeDip - shadow_margin.width(), 159 kBackgroundInitSizeDip - shadow_margin.width(),
98 kBackgroundInitSizeDip - shadow_margin.height())); 160 kBackgroundInitSizeDip - shadow_margin.height()));
99 Add(shadow_layer_.get()); 161 Add(shadow_layer_.get());
100 } 162 }
101 ~VoiceInteractionIconBackground() override{}; 163 ~VoiceInteractionIconBackground() override{};
102 164
165 void AnimateToLarge(const gfx::PointF& new_center,
166 ui::LayerAnimationObserver* animation_observer) {
167 PaintedShapeTransforms transforms;
168 // Setup the painted layers to be the small round size and show it
169 CalculateCircleTransforms(small_size_, &transforms);
170 SetTransforms(transforms);
171 SetPaintedLayersVisible(true);
172
173 // Hide the shadow layer
174 shadow_layer_->SetVisible(false);
175
176 center_point_ = new_center;
177 // Animate the painted layers to the large rectangle size
178 CalculateRectTransforms(large_size_, kBackgroundCornerRadiusDip,
179 &transforms);
180
181 AnimateToTransforms(
182 transforms,
183 base::TimeDelta::FromMilliseconds(kBackgroundMorphDurationMs),
184 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
185 gfx::Tween::LINEAR_OUT_SLOW_IN, animation_observer);
186 }
187
188 void ResetShape() {
189 // This reverts to the original small round shape.
190 shadow_layer_->SetVisible(true);
191 SetPaintedLayersVisible(false);
192 center_point_.SetPoint(small_size_.width() / 2.f,
193 small_size_.height() / 2.f);
194 }
195
103 private: 196 private:
197 // Enumeration of the different shapes that compose the background.
198 enum class PaintedShape {
199 TOP_LEFT_CIRCLE = 0,
200 TOP_RIGHT_CIRCLE,
201 BOTTOM_RIGHT_CIRCLE,
202 BOTTOM_LEFT_CIRCLE,
203 HORIZONTAL_RECT,
204 VERTICAL_RECT,
205 // The total number of shapes, not an actual shape.
206 PAINTED_SHAPE_COUNT
207 };
oshima 2017/07/07 19:15:38 How about moving this to anonymous class, and defi
xc 2017/07/07 23:35:39 changed back to enum.
208
209 typedef gfx::Transform PaintedShapeTransforms[static_cast<int>(
210 PaintedShape::PAINTED_SHAPE_COUNT)];
211
212 void AddPaintLayer(PaintedShape painted_shape) {
213 ui::LayerDelegate* delegate = nullptr;
214 switch (painted_shape) {
215 case PaintedShape::TOP_LEFT_CIRCLE:
216 case PaintedShape::TOP_RIGHT_CIRCLE:
217 case PaintedShape::BOTTOM_RIGHT_CIRCLE:
218 case PaintedShape::BOTTOM_LEFT_CIRCLE:
219 delegate = circle_layer_delegate_.get();
220 break;
221 case PaintedShape::HORIZONTAL_RECT:
222 case PaintedShape::VERTICAL_RECT:
223 delegate = rect_layer_delegate_.get();
224 break;
225 case PaintedShape::PAINTED_SHAPE_COUNT:
226 NOTREACHED() << "PAINTED_SHAPE_COUNT is not an actual shape type.";
227 break;
228 }
229
230 ui::Layer* layer = new ui::Layer();
231 Add(layer);
232
233 layer->SetBounds(gfx::Rect(small_size_));
234 layer->SetFillsBoundsOpaquely(false);
235 layer->set_delegate(delegate);
236 layer->SetVisible(true);
237 layer->SetOpacity(1.0);
238 layer->SetMasksToBounds(false);
239 layer->set_name("PAINTED_SHAPE_COUNT:" + ToLayerName(painted_shape));
240
241 painted_layers_[static_cast<int>(painted_shape)].reset(layer);
242 }
243
244 void SetTransforms(const PaintedShapeTransforms transforms) {
245 for (int i = 0; i < static_cast<int>(PaintedShape::PAINTED_SHAPE_COUNT);
246 ++i)
oshima 2017/07/07 19:15:37 kAllShapse
xc 2017/07/07 23:35:39 changed back to enum
247 painted_layers_[i]->SetTransform(transforms[i]);
248 }
249
250 void SetPaintedLayersVisible(bool visible) {
251 for (int i = 0; i < static_cast<int>(PaintedShape::PAINTED_SHAPE_COUNT);
252 ++i)
oshima 2017/07/07 19:15:37 ditto
xc 2017/07/07 23:35:39 changed back to enum
253 painted_layers_[i]->SetVisible(visible);
254 }
255
256 void CalculateCircleTransforms(const gfx::Size& size,
257 PaintedShapeTransforms* transforms_out) const {
258 CalculateRectTransforms(size, std::min(size.width(), size.height()) / 2.0f,
259 transforms_out);
260 }
261
262 void CalculateRectTransforms(const gfx::Size& desired_size,
263 float corner_radius,
264 PaintedShapeTransforms* transforms_out) const {
265 DCHECK_GE(desired_size.width() / 2.0f, corner_radius)
266 << "The circle's diameter should not be greater than the total width.";
267 DCHECK_GE(desired_size.height() / 2.0f, corner_radius)
268 << "The circle's diameter should not be greater than the total height.";
269
270 gfx::SizeF size(desired_size);
271 // This function can be called before the layer's been added to a view,
272 // either at construction time or in tests.
273 if (GetCompositor()) {
274 // Modify |desired_size| so that the ripple aligns to pixel bounds.
275 const float dsf = GetCompositor()->device_scale_factor();
276 gfx::RectF ripple_bounds((gfx::PointF(center_point_)), gfx::SizeF());
277 ripple_bounds.Inset(-gfx::InsetsF(desired_size.height() / 2.0f,
278 desired_size.width() / 2.0f));
279 ripple_bounds.Scale(dsf);
280 ripple_bounds = gfx::RectF(gfx::ToEnclosingRect(ripple_bounds));
oshima 2017/07/06 22:04:42 gfx::ScaleToEnclosingRect?
xc 2017/07/07 16:38:15 This one does not support RectF
oshima 2017/07/07 19:15:38 Doh, too bad.
xc 2017/07/07 23:35:39 Acknowledged.
281 ripple_bounds.Scale(1.0f / dsf);
282 size = ripple_bounds.size();
283 }
284
285 // The shapes are drawn such that their center points are not at the origin.
286 // Thus we use the CalculateCircleTransform() and CalculateRectTransform()
287 // methods to calculate the complex Transforms.
288
289 const float circle_scale = std::max(
290 kMinimumCircleScale,
291 corner_radius / static_cast<float>(circle_layer_delegate_->radius()));
292
293 const float circle_target_x_offset = size.width() / 2.0f - corner_radius;
294 const float circle_target_y_offset = size.height() / 2.0f - corner_radius;
295
296 (*transforms_out)[static_cast<int>(PaintedShape::TOP_LEFT_CIRCLE)] =
297 CalculateCircleTransform(circle_scale, -circle_target_x_offset,
298 -circle_target_y_offset);
299 (*transforms_out)[static_cast<int>(PaintedShape::TOP_RIGHT_CIRCLE)] =
300 CalculateCircleTransform(circle_scale, circle_target_x_offset,
301 -circle_target_y_offset);
302 (*transforms_out)[static_cast<int>(PaintedShape::BOTTOM_RIGHT_CIRCLE)] =
303 CalculateCircleTransform(circle_scale, circle_target_x_offset,
304 circle_target_y_offset);
305 (*transforms_out)[static_cast<int>(PaintedShape::BOTTOM_LEFT_CIRCLE)] =
306 CalculateCircleTransform(circle_scale, -circle_target_x_offset,
307 circle_target_y_offset);
308
309 const float rect_delegate_width = rect_layer_delegate_->size().width();
310 const float rect_delegate_height = rect_layer_delegate_->size().height();
311
312 (*transforms_out)[static_cast<int>(PaintedShape::HORIZONTAL_RECT)] =
313 CalculateRectTransform(
314 std::max(kMinimumRectScale, size.width() / rect_delegate_width),
315 std::max(kMinimumRectScale, (size.height() - 2.0f * corner_radius) /
316 rect_delegate_height));
317
318 (*transforms_out)[static_cast<int>(PaintedShape::VERTICAL_RECT)] =
319 CalculateRectTransform(
320 std::max(kMinimumRectScale, (size.width() - 2.0f * corner_radius) /
321 rect_delegate_width),
322 std::max(kMinimumRectScale, size.height() / rect_delegate_height));
323 }
324
325 gfx::Transform CalculateCircleTransform(float scale,
326 float target_center_x,
327 float target_center_y) const {
328 gfx::Transform transform;
329 // Offset for the center point of the ripple.
330 transform.Translate(center_point_.x(), center_point_.y());
331 // Move circle to target.
332 transform.Translate(target_center_x, target_center_y);
333 transform.Scale(scale, scale);
334 // Align center point of the painted circle.
335 const gfx::Vector2dF circle_center_offset =
336 circle_layer_delegate_->GetCenteringOffset();
337 transform.Translate(-circle_center_offset.x(), -circle_center_offset.y());
338 return transform;
339 }
340
341 gfx::Transform CalculateRectTransform(float x_scale, float y_scale) const {
342 gfx::Transform transform;
343 transform.Translate(center_point_.x(), center_point_.y());
344 transform.Scale(x_scale, y_scale);
345 const gfx::Vector2dF rect_center_offset =
346 rect_layer_delegate_->GetCenteringOffset();
347 transform.Translate(-rect_center_offset.x(), -rect_center_offset.y());
348 return transform;
349 }
350
351 void AnimateToTransforms(
352 const PaintedShapeTransforms transforms,
353 base::TimeDelta duration,
354 ui::LayerAnimator::PreemptionStrategy preemption_strategy,
355 gfx::Tween::Type tween,
356 ui::LayerAnimationObserver* animation_observer) {
357 for (int i = 0; i < static_cast<int>(PaintedShape::PAINTED_SHAPE_COUNT);
358 ++i) {
359 ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator();
360 ui::ScopedLayerAnimationSettings animation(animator);
361 animation.SetPreemptionStrategy(preemption_strategy);
362 animation.SetTweenType(tween);
363 std::unique_ptr<ui::LayerAnimationElement> element =
364 ui::LayerAnimationElement::CreateTransformElement(transforms[i],
365 duration);
366 ui::LayerAnimationSequence* sequence =
367 new ui::LayerAnimationSequence(std::move(element));
368
369 if (animation_observer)
370 sequence->AddObserver(animation_observer);
371
372 animator->StartAnimation(sequence);
373 }
374 }
375
376 std::string ToLayerName(PaintedShape painted_shape) {
377 switch (painted_shape) {
378 case PaintedShape::TOP_LEFT_CIRCLE:
379 return "TOP_LEFT_CIRCLE";
380 case PaintedShape::TOP_RIGHT_CIRCLE:
381 return "TOP_RIGHT_CIRCLE";
382 case PaintedShape::BOTTOM_RIGHT_CIRCLE:
383 return "BOTTOM_RIGHT_CIRCLE";
384 case PaintedShape::BOTTOM_LEFT_CIRCLE:
385 return "BOTTOM_LEFT_CIRCLE";
386 case PaintedShape::HORIZONTAL_RECT:
387 return "HORIZONTAL_RECT";
388 case PaintedShape::VERTICAL_RECT:
389 return "VERTICAL_RECT";
390 case PaintedShape::PAINTED_SHAPE_COUNT:
391 NOTREACHED() << "The PAINTED_SHAPE_COUNT value should never be used.";
392 return "PAINTED_SHAPE_COUNT";
393 }
394 return "UNKNOWN";
395 }
396
104 void OnPaintLayer(const ui::PaintContext& context) override { 397 void OnPaintLayer(const ui::PaintContext& context) override {
105 // Radius is based on the parent layer size, the shadow layer is expanded 398 // Radius is based on the parent layer size, the shadow layer is expanded
106 // to make room for the shadow. 399 // to make room for the shadow.
107 float radius = size().width() / 2.f; 400 float radius = size().width() / 2.f;
108 401
109 ui::PaintRecorder recorder(context, shadow_layer_->size()); 402 ui::PaintRecorder recorder(context, shadow_layer_->size());
110 gfx::Canvas* canvas = recorder.canvas(); 403 gfx::Canvas* canvas = recorder.canvas();
111 404
112 cc::PaintFlags flags; 405 cc::PaintFlags flags;
113 flags.setColor(SK_ColorWHITE); 406 flags.setColor(SK_ColorWHITE);
114 flags.setAntiAlias(true); 407 flags.setAntiAlias(true);
115 flags.setStyle(cc::PaintFlags::kFill_Style); 408 flags.setStyle(cc::PaintFlags::kFill_Style);
116 flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_)); 409 flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_));
117 gfx::Rect shadow_bounds = shadow_layer_->bounds(); 410 gfx::Rect shadow_bounds = shadow_layer_->bounds();
118 canvas->DrawCircle( 411 canvas->DrawCircle(
119 gfx::PointF(radius - shadow_bounds.x(), radius - shadow_bounds.y()), 412 gfx::PointF(radius - shadow_bounds.x(), radius - shadow_bounds.y()),
120 radius, flags); 413 radius, flags);
121 } 414 }
122 415
123 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} 416 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
124 417
125 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} 418 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
126 419
420 // ui::Layers for all of the painted shape layers that compose the morphing
421 // shape.
422 std::unique_ptr<ui::Layer>
423 painted_layers_[static_cast<int>(PaintedShape::PAINTED_SHAPE_COUNT)];
oshima 2017/07/06 22:04:42 alternatively, you can do std::map<PaintedShape,
xc 2017/07/07 16:38:15 isn't map much slower than just indexing an array?
oshima 2017/07/07 19:15:39 std::map is implemented as a tree and accessing it
xc 2017/07/07 23:35:39 changed back to enum as discussed offline.
424
425 const gfx::Size large_size_;
426
427 const gfx::Size small_size_;
oshima 2017/07/06 22:04:42 looks like SizeF is better choice?
xc 2017/07/07 16:38:15 I have to use this to set the layer bounds, which
428
429 // The center point of the painted shape.
430 gfx::PointF center_point_;
431
432 // ui::LayerDelegate to paint circles for all the circle layers.
433 std::unique_ptr<views::CircleLayerDelegate> circle_layer_delegate_;
434
435 // ui::LayerDelegate to paint rectangles for all the rectangle layers.
436 std::unique_ptr<views::RectangleLayerDelegate> rect_layer_delegate_;
437
127 gfx::ShadowValues shadow_values_; 438 gfx::ShadowValues shadow_values_;
128 439
129 std::unique_ptr<ui::Layer> shadow_layer_; 440 std::unique_ptr<ui::Layer> shadow_layer_;
130 441
131 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIconBackground); 442 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIconBackground);
132 }; 443 };
133 444
134 class VoiceInteractionIcon : public ui::Layer, public ui::LayerDelegate {
135 public:
136 VoiceInteractionIcon() {
137 set_name("VoiceInteractionOverlay:ICON_LAYER");
138 SetBounds(gfx::Rect(0, 0, kIconInitSizeDip, kIconInitSizeDip));
139 SetFillsBoundsOpaquely(false);
140 SetMasksToBounds(false);
141 set_delegate(this);
142 }
143
144 private:
145 void OnPaintLayer(const ui::PaintContext& context) override {
146 ui::PaintRecorder recorder(context, size());
147 gfx::PaintVectorIcon(recorder.canvas(), kShelfVoiceInteractionIcon,
148 kIconInitSizeDip, 0);
149 }
150
151 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
152
153 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
154
155 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIcon);
156 };
157 } // namespace
158
159 VoiceInteractionOverlay::VoiceInteractionOverlay(AppListButton* host_view) 445 VoiceInteractionOverlay::VoiceInteractionOverlay(AppListButton* host_view)
160 : ripple_layer_(new ui::Layer()), 446 : ripple_layer_(new ui::Layer()),
161 icon_layer_(new VoiceInteractionIcon()), 447 icon_layer_(new VoiceInteractionIcon()),
162 background_layer_(new VoiceInteractionIconBackground()), 448 background_layer_(new VoiceInteractionIconBackground()),
163 host_view_(host_view), 449 host_view_(host_view),
164 is_bursting_(false), 450 is_bursting_(false),
oshima 2017/07/06 22:04:42 initialize show_icons_ and should_hide_animation_
xc 2017/07/07 16:38:15 Done. Generally is it preferred to init here or in
oshima 2017/07/07 19:15:38 I usually initialize bool/(null)pointer in header,
xc 2017/07/07 23:35:39 Acknowledged.
165 circle_layer_delegate_(kRippleColor, kRippleCircleInitRadiusDip) { 451 circle_layer_delegate_(kRippleColor, kRippleCircleInitRadiusDip) {
166 SetPaintToLayer(ui::LAYER_NOT_DRAWN); 452 SetPaintToLayer(ui::LAYER_NOT_DRAWN);
167 layer()->set_name("VoiceInteractionOverlay:ROOT_LAYER"); 453 layer()->set_name("VoiceInteractionOverlay:ROOT_LAYER");
168 layer()->SetMasksToBounds(false); 454 layer()->SetMasksToBounds(false);
169 455
170 ripple_layer_->SetBounds(gfx::Rect(0, 0, kRippleCircleInitRadiusDip * 2, 456 ripple_layer_->SetBounds(gfx::Rect(0, 0, kRippleCircleInitRadiusDip * 2,
171 kRippleCircleInitRadiusDip * 2)); 457 kRippleCircleInitRadiusDip * 2));
172 ripple_layer_->set_delegate(&circle_layer_delegate_); 458 ripple_layer_->set_delegate(&circle_layer_delegate_);
173 ripple_layer_->SetFillsBoundsOpaquely(false); 459 ripple_layer_->SetFillsBoundsOpaquely(false);
174 ripple_layer_->SetMasksToBounds(true); 460 ripple_layer_->SetMasksToBounds(true);
175 ripple_layer_->set_name("VoiceInteractionOverlay:PAINTED_LAYER"); 461 ripple_layer_->set_name("VoiceInteractionOverlay:PAINTED_LAYER");
176 layer()->Add(ripple_layer_.get()); 462 layer()->Add(ripple_layer_.get());
177 463
178 layer()->Add(background_layer_.get()); 464 layer()->Add(background_layer_.get());
179 465
180 layer()->Add(icon_layer_.get()); 466 layer()->Add(icon_layer_.get());
181 } 467 }
182 468
183 VoiceInteractionOverlay::~VoiceInteractionOverlay() {} 469 VoiceInteractionOverlay::~VoiceInteractionOverlay() {}
184 470
185 void VoiceInteractionOverlay::StartAnimation() { 471 void VoiceInteractionOverlay::StartAnimation(bool show_icon) {
186 is_bursting_ = false; 472 is_bursting_ = false;
473 show_icon_ = show_icon;
187 SetVisible(true); 474 SetVisible(true);
188 475
189 // Setup ripple initial state. 476 // Setup ripple initial state.
190 ripple_layer_->SetOpacity(0); 477 ripple_layer_->SetOpacity(0);
191 478
192 SkMScalar scale_factor = 479 SkMScalar scale_factor =
193 kRippleCircleStartRadiusDip / kRippleCircleInitRadiusDip; 480 kRippleCircleStartRadiusDip / kRippleCircleInitRadiusDip;
194 gfx::Transform transform; 481 gfx::Transform transform;
195 482
196 const gfx::Point center = host_view_->GetCenterPoint(); 483 const gfx::Point center = host_view_->GetCenterPoint();
(...skipping 15 matching lines...) Expand all
212 base::TimeDelta::FromMilliseconds(kRippleExpandDurationMs)); 499 base::TimeDelta::FromMilliseconds(kRippleExpandDurationMs));
213 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); 500 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2);
214 501
215 ripple_layer_->SetTransform(transform); 502 ripple_layer_->SetTransform(transform);
216 503
217 settings.SetTransitionDuration( 504 settings.SetTransitionDuration(
218 base::TimeDelta::FromMilliseconds(kRippleOpacityDurationMs)); 505 base::TimeDelta::FromMilliseconds(kRippleOpacityDurationMs));
219 ripple_layer_->SetOpacity(kRippleOpacity); 506 ripple_layer_->SetOpacity(kRippleOpacity);
220 } 507 }
221 508
222 // We need to determine the animation direction based on shelf alignment. 509 icon_layer_->SetOpacity(0);
223 ShelfAlignment alignment = 510 background_layer_->SetOpacity(0);
224 Shelf::ForWindow(host_view_->GetWidget()->GetNativeWindow())->alignment(); 511 if (!show_icon_)
512 return;
225 513
226 // Setup icon initial state. 514 // Setup icon initial state.
227 icon_layer_->SetOpacity(0);
228 transform.MakeIdentity(); 515 transform.MakeIdentity();
229
230 transform.Translate(center.x() - kIconStartSizeDip / 2.f, 516 transform.Translate(center.x() - kIconStartSizeDip / 2.f,
231 center.y() - kIconStartSizeDip / 2.f); 517 center.y() - kIconStartSizeDip / 2.f);
232 518
233 scale_factor = kIconStartSizeDip / kIconInitSizeDip; 519 scale_factor = kIconStartSizeDip / kIconInitSizeDip;
234 transform.Scale(scale_factor, scale_factor); 520 transform.Scale(scale_factor, scale_factor);
235 icon_layer_->SetTransform(transform); 521 icon_layer_->SetTransform(transform);
236 522
237 // Setup icon animation. 523 // Setup icon animation.
238 scale_factor = kIconSizeDip / kIconInitSizeDip; 524 scale_factor = kIconSizeDip / kIconInitSizeDip;
239 transform.MakeIdentity(); 525 transform.MakeIdentity();
240 if (alignment == SHELF_ALIGNMENT_BOTTOM || 526 transform.Translate(center.x() - kIconSizeDip / 2 + kIconOffsetDip,
241 alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) { 527 center.y() - kIconSizeDip / 2 - kIconOffsetDip);
242 transform.Translate(center.x() - kIconSizeDip / 2 + kIconOffsetDip,
243 center.y() - kIconSizeDip / 2 - kIconOffsetDip);
244 } else if (alignment == SHELF_ALIGNMENT_RIGHT) {
245 transform.Translate(center.x() - kIconSizeDip / 2 - kIconOffsetDip,
246 center.y() - kIconSizeDip / 2 + kIconOffsetDip);
247 } else {
248 DCHECK_EQ(alignment, SHELF_ALIGNMENT_LEFT);
249 transform.Translate(center.x() - kIconSizeDip / 2 + kIconOffsetDip,
250 center.y() - kIconSizeDip / 2 + kIconOffsetDip);
251 }
252 transform.Scale(scale_factor, scale_factor); 528 transform.Scale(scale_factor, scale_factor);
253 529
254 { 530 {
255 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); 531 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator());
256 settings.SetTransitionDuration( 532 settings.SetTransitionDuration(
257 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs)); 533 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs));
258 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); 534 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2);
259 535
260 icon_layer_->SetTransform(transform); 536 icon_layer_->SetTransform(transform);
261 icon_layer_->SetOpacity(kIconOpacity); 537 icon_layer_->SetOpacity(kIconOpacity);
262 } 538 }
263 539
264 // Setup background initial state. 540 // Setup background initial state.
265 background_layer_->SetOpacity(0); 541 background_layer_->ResetShape();
266 542
267 transform.MakeIdentity(); 543 transform.MakeIdentity();
268 transform.Translate(center.x() - kBackgroundStartSizeDip / 2.f, 544 transform.Translate(center.x() - kBackgroundStartSizeDip / 2.f,
269 center.y() - kBackgroundStartSizeDip / 2.f); 545 center.y() - kBackgroundStartSizeDip / 2.f);
270 546
271 scale_factor = kBackgroundStartSizeDip / kBackgroundInitSizeDip; 547 scale_factor = kBackgroundStartSizeDip / kBackgroundInitSizeDip;
272 transform.Scale(scale_factor, scale_factor); 548 transform.Scale(scale_factor, scale_factor);
273 background_layer_->SetTransform(transform); 549 background_layer_->SetTransform(transform);
274 550
275 // Setup background animation. 551 // Setup background animation.
276 scale_factor = kBackgroundSizeDip / kBackgroundInitSizeDip; 552 scale_factor = kBackgroundSizeDip / kBackgroundInitSizeDip;
277 transform.MakeIdentity(); 553 transform.MakeIdentity();
278 if (alignment == SHELF_ALIGNMENT_BOTTOM || 554 transform.Translate(center.x() - kBackgroundSizeDip / 2 + kIconOffsetDip,
279 alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) { 555 center.y() - kBackgroundSizeDip / 2 - kIconOffsetDip);
280 transform.Translate(center.x() - kBackgroundSizeDip / 2 + kIconOffsetDip,
281 center.y() - kBackgroundSizeDip / 2 - kIconOffsetDip);
282 } else if (alignment == SHELF_ALIGNMENT_RIGHT) {
283 transform.Translate(center.x() - kBackgroundSizeDip / 2 - kIconOffsetDip,
284 center.y() - kBackgroundSizeDip / 2 + kIconOffsetDip);
285 } else {
286 DCHECK_EQ(alignment, SHELF_ALIGNMENT_LEFT);
287 transform.Translate(center.x() - kBackgroundSizeDip / 2 + kIconOffsetDip,
288 center.y() - kBackgroundSizeDip / 2 + kIconOffsetDip);
289 }
290 transform.Scale(scale_factor, scale_factor); 556 transform.Scale(scale_factor, scale_factor);
291 557
292 { 558 {
293 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); 559 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator());
294 settings.SetTransitionDuration( 560 settings.SetTransitionDuration(
295 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs)); 561 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs));
296 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); 562 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2);
297 563
298 background_layer_->SetTransform(transform); 564 background_layer_->SetTransform(transform);
299 } 565 }
300 566
301 { 567 {
302 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); 568 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator());
303 settings.SetTransitionDuration( 569 settings.SetTransitionDuration(
304 base::TimeDelta::FromMilliseconds(kBackgroundOpacityDurationMs)); 570 base::TimeDelta::FromMilliseconds(kBackgroundOpacityDurationMs));
305 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); 571 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2);
306 572
307 background_layer_->SetOpacity(1); 573 background_layer_->SetOpacity(1);
308 } 574 }
309 } 575 }
310 576
311 void VoiceInteractionOverlay::BurstAnimation() { 577 void VoiceInteractionOverlay::BurstAnimation() {
312 is_bursting_ = true; 578 is_bursting_ = true;
579 should_hide_animation_ = false;
313 580
314 gfx::Point center = host_view_->GetCenterPoint(); 581 gfx::Point center = host_view_->GetCenterPoint();
582 gfx::Transform transform;
315 583
316 // Setup ripple animations. 584 // Setup ripple animations.
317 { 585 {
318 SkMScalar scale_factor = 586 SkMScalar scale_factor =
319 kRippleCircleBurstRadiusDip / kRippleCircleInitRadiusDip; 587 kRippleCircleBurstRadiusDip / kRippleCircleInitRadiusDip;
320 std::unique_ptr<gfx::Transform> transform(new gfx::Transform()); 588 transform.Translate(center.x() - kRippleCircleBurstRadiusDip,
321 transform->Translate(center.x() - kRippleCircleBurstRadiusDip, 589 center.y() - kRippleCircleBurstRadiusDip);
322 center.y() - kRippleCircleBurstRadiusDip); 590 transform.Scale(scale_factor, scale_factor);
323 transform->Scale(scale_factor, scale_factor);
324 591
325 ui::ScopedLayerAnimationSettings settings(ripple_layer_->GetAnimator()); 592 ui::ScopedLayerAnimationSettings settings(ripple_layer_->GetAnimator());
326 settings.SetTransitionDuration( 593 settings.SetTransitionDuration(
327 base::TimeDelta::FromMilliseconds(kFullBurstDurationMs)); 594 base::TimeDelta::FromMilliseconds(kFullBurstDurationMs));
328 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); 595 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
596 settings.SetPreemptionStrategy(
597 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION);
329 598
330 ripple_layer_->SetTransform(*transform.get()); 599 ripple_layer_->SetTransform(transform);
331 ripple_layer_->SetOpacity(0); 600 ripple_layer_->SetOpacity(0);
332 } 601 }
333 602
603 if (!show_icon_)
604 return;
605
334 // Setup icon animation. 606 // Setup icon animation.
335 { 607 {
336 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); 608 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator());
337 settings.SetTransitionDuration( 609 settings.SetTransitionDuration(
338 base::TimeDelta::FromMilliseconds(kIconBurstDurationMs)); 610 base::TimeDelta::FromMilliseconds(kBackgroundMorphDurationMs));
611 settings.SetPreemptionStrategy(
612 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION);
339 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); 613 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
340 614
341 icon_layer_->SetOpacity(0); 615 transform.MakeIdentity();
616 transform.Translate(kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip -
617 kIconEndSizeDip / 2,
618 -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip -
619 kIconEndSizeDip / 2);
620 SkMScalar scale_factor = kIconEndSizeDip / kIconInitSizeDip;
621 transform.Scale(scale_factor, scale_factor);
622
623 icon_layer_->SetTransform(transform);
342 } 624 }
343 625
344 // Setup background animation. 626 // Setup background animation.
345 { 627 ui::CallbackLayerAnimationObserver* observer =
346 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); 628 new ui::CallbackLayerAnimationObserver(
347 settings.SetTransitionDuration( 629 base::Bind(&VoiceInteractionOverlay::AnimationEndedCallback,
348 base::TimeDelta::FromMilliseconds(kIconBurstDurationMs)); 630 base::Unretained(this)));
349 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); 631 // Transform to new shape.
632 // We want to animate from the background's current position into a larger
633 // size. The animation moves the background's center point while morphing from
634 // circle to a rectangle.
635 float x_offset = center.x() - kBackgroundSizeDip / 2 + kIconOffsetDip;
636 float y_offset = center.y() - kBackgroundSizeDip / 2 - kIconOffsetDip;
350 637
351 background_layer_->SetOpacity(0); 638 background_layer_->AnimateToLarge(
352 } 639 gfx::PointF(
640 kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip - x_offset,
641 -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip - y_offset),
642 observer);
643 observer->SetActive();
353 } 644 }
354 645
355 void VoiceInteractionOverlay::EndAnimation() { 646 void VoiceInteractionOverlay::EndAnimation() {
356 if (is_bursting_) { 647 if (is_bursting_) {
357 // Too late, user action already fired, we have to finish what's started. 648 // Too late, user action already fired, we have to finish what's started.
358 return; 649 return;
359 } 650 }
360 651
361 // Play reverse animation 652 // Play reverse animation
362 // Setup ripple animations. 653 // Setup ripple animations.
(...skipping 14 matching lines...) Expand all
377 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs)); 668 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs));
378 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN); 669 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN);
379 670
380 ripple_layer_->SetTransform(transform); 671 ripple_layer_->SetTransform(transform);
381 672
382 settings.SetTransitionDuration( 673 settings.SetTransitionDuration(
383 base::TimeDelta::FromMilliseconds(kRippleOpacityRetractDurationMs)); 674 base::TimeDelta::FromMilliseconds(kRippleOpacityRetractDurationMs));
384 ripple_layer_->SetOpacity(0); 675 ripple_layer_->SetOpacity(0);
385 } 676 }
386 677
678 if (!show_icon_)
679 return;
680
387 // Setup icon animation. 681 // Setup icon animation.
388 transform.MakeIdentity(); 682 transform.MakeIdentity();
389 683
390 transform.Translate(center.x() - kIconStartSizeDip / 2.f, 684 transform.Translate(center.x() - kIconStartSizeDip / 2.f,
391 center.y() - kIconStartSizeDip / 2.f); 685 center.y() - kIconStartSizeDip / 2.f);
392 686
393 scale_factor = kIconStartSizeDip / kIconInitSizeDip; 687 scale_factor = kIconStartSizeDip / kIconInitSizeDip;
394 transform.Scale(scale_factor, scale_factor); 688 transform.Scale(scale_factor, scale_factor);
395 689
396 { 690 {
(...skipping 23 matching lines...) Expand all
420 IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 714 IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
421 settings.SetTransitionDuration( 715 settings.SetTransitionDuration(
422 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs)); 716 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs));
423 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN); 717 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN);
424 718
425 background_layer_->SetTransform(transform); 719 background_layer_->SetTransform(transform);
426 background_layer_->SetOpacity(0); 720 background_layer_->SetOpacity(0);
427 } 721 }
428 } 722 }
429 723
724 void VoiceInteractionOverlay::HideAnimation() {
725 is_bursting_ = false;
726
727 should_hide_animation_ = true;
oshima 2017/07/06 22:04:42 should this be inside following if, and reset afte
xc 2017/07/07 16:38:15 Done.
728 if (background_layer_->GetAnimator()->is_animating()) {
729 // Wait for current animation to finish
730 return;
731 }
732
733 // Setup ripple animations.
734 {
735 ui::ScopedLayerAnimationSettings settings(ripple_layer_->GetAnimator());
736 settings.SetTransitionDuration(
737 base::TimeDelta::FromMilliseconds(kHideDurationMs));
738 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
739 settings.SetPreemptionStrategy(
740 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION);
741
742 ripple_layer_->SetOpacity(0);
743 }
744
745 // Setup icon animation.
746 {
747 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator());
748 settings.SetTransitionDuration(
749 base::TimeDelta::FromMilliseconds(kHideDurationMs));
750 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
751 settings.SetPreemptionStrategy(
752 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION);
753
754 icon_layer_->SetOpacity(0);
755 }
756
757 // Setup background animation.
758 {
759 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator());
760 settings.SetTransitionDuration(
761 base::TimeDelta::FromMilliseconds(kHideDurationMs));
762 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
763 settings.SetPreemptionStrategy(
764 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION);
765
766 background_layer_->SetOpacity(0);
767 }
768 }
769
770 bool VoiceInteractionOverlay::AnimationEndedCallback(
771 const ui::CallbackLayerAnimationObserver& observer) {
772 if (should_hide_animation_)
773 HideAnimation();
774
775 return true;
776 }
777
430 } // namespace ash 778 } // namespace ash
OLDNEW
« ash/shelf/voice_interaction_overlay.h ('K') | « ash/shelf/voice_interaction_overlay.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698