OLD | NEW |
---|---|
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: | |
oshima
2017/07/06 19:23:54
// ui::LayerDelegate:
xiaohuic
2017/07/06 20:55:41
Done.
| |
109 void OnPaintLayer(const ui::PaintContext& context) override { | |
110 ui::PaintRecorder recorder(context, size()); | |
111 gfx::PaintVectorIcon(recorder.canvas(), kShelfVoiceInteractionIcon, | |
112 kIconInitSizeDip, 0); | |
113 } | |
114 | |
115 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} | |
116 | |
117 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} | |
118 | |
119 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIcon); | |
120 }; | |
121 } // namespace | |
77 | 122 |
78 class VoiceInteractionIconBackground : public ui::Layer, | 123 class VoiceInteractionIconBackground : public ui::Layer, |
79 public ui::LayerDelegate { | 124 public ui::LayerDelegate { |
80 public: | 125 public: |
81 VoiceInteractionIconBackground() : Layer(ui::LAYER_NOT_DRAWN) { | 126 enum Shape { CIRCLE, ROUNDED_RECT }; |
oshima
2017/07/06 19:23:55
nit: enum class
xiaohuic
2017/07/06 20:55:41
Done.
| |
127 | |
128 VoiceInteractionIconBackground() | |
129 : Layer(ui::LAYER_NOT_DRAWN), | |
130 large_size_( | |
131 gfx::Size(kBackgroundLargeWidthDip, kBackgroundLargeHeightDip)), | |
oshima
2017/07/06 19:23:55
looks like it's now ok to use brace initialization
xiaohuic
2017/07/06 20:55:41
Acknowledged.
| |
132 small_size_(gfx::Size(kBackgroundSizeDip, kBackgroundSizeDip)), | |
133 center_point_( | |
134 gfx::PointF(kBackgroundSizeDip / 2, kBackgroundSizeDip / 2)), | |
135 circle_layer_delegate_( | |
136 new views::CircleLayerDelegate(SK_ColorWHITE, | |
137 kBackgroundSizeDip / 2)), | |
138 rect_layer_delegate_( | |
139 new views::RectangleLayerDelegate(SK_ColorWHITE, | |
140 gfx::SizeF(small_size_))) { | |
82 set_name("VoiceInteractionOverlay:BACKGROUND_LAYER"); | 141 set_name("VoiceInteractionOverlay:BACKGROUND_LAYER"); |
83 SetBounds(gfx::Rect(0, 0, kBackgroundInitSizeDip, kBackgroundInitSizeDip)); | 142 SetBounds(gfx::Rect(0, 0, kBackgroundInitSizeDip, kBackgroundInitSizeDip)); |
84 SetFillsBoundsOpaquely(false); | 143 SetFillsBoundsOpaquely(false); |
85 SetMasksToBounds(false); | 144 SetMasksToBounds(false); |
86 | 145 |
146 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) | |
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, | |
oshima
2017/07/06 19:23:54
PointF&
xiaohuic
2017/07/06 20:55:41
Done.
| |
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_ = | |
oshima
2017/07/06 19:23:54
center_point_.SetPoint()
xiaohuic
2017/07/06 20:55:41
Done.
| |
193 gfx::PointF(small_size_.width() / 2.f, small_size_.height() / 2.f); | |
194 } | |
195 | |
103 private: | 196 private: |
197 // Enumeration of the different shapes that compose the background. | |
198 enum PaintedShape { | |
oshima
2017/07/06 19:23:55
enum class
xiaohuic
2017/07/06 20:55:41
Done.
| |
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 }; | |
208 | |
209 typedef gfx::Transform PaintedShapeTransforms[PAINTED_SHAPE_COUNT]; | |
210 | |
211 void AddPaintLayer(PaintedShape painted_shape) { | |
212 ui::LayerDelegate* delegate = nullptr; | |
213 switch (painted_shape) { | |
214 case TOP_LEFT_CIRCLE: | |
215 case TOP_RIGHT_CIRCLE: | |
216 case BOTTOM_RIGHT_CIRCLE: | |
217 case BOTTOM_LEFT_CIRCLE: | |
218 delegate = circle_layer_delegate_.get(); | |
219 break; | |
220 case HORIZONTAL_RECT: | |
221 case VERTICAL_RECT: | |
222 delegate = rect_layer_delegate_.get(); | |
223 break; | |
224 case PAINTED_SHAPE_COUNT: | |
225 NOTREACHED() << "PAINTED_SHAPE_COUNT is not an actual shape type."; | |
226 break; | |
227 } | |
228 | |
229 ui::Layer* layer = new ui::Layer(); | |
230 Add(layer); | |
231 | |
232 layer->SetBounds(gfx::Rect(small_size_)); | |
233 layer->SetFillsBoundsOpaquely(false); | |
234 layer->set_delegate(delegate); | |
235 layer->SetVisible(true); | |
236 layer->SetOpacity(1.0); | |
237 layer->SetMasksToBounds(false); | |
238 layer->set_name("PAINTED_SHAPE_COUNT:" + ToLayerName(painted_shape)); | |
239 | |
240 painted_layers_[painted_shape].reset(layer); | |
241 } | |
242 | |
243 void SetTransforms(const PaintedShapeTransforms transforms) { | |
244 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) | |
245 painted_layers_[i]->SetTransform(transforms[i]); | |
246 } | |
247 | |
248 void SetPaintedLayersVisible(bool visible) { | |
249 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) | |
250 painted_layers_[i]->SetVisible(visible); | |
251 } | |
252 | |
253 void CalculateCircleTransforms(const gfx::Size& size, | |
254 PaintedShapeTransforms* transforms_out) const { | |
255 CalculateRectTransforms(size, std::min(size.width(), size.height()) / 2.0f, | |
256 transforms_out); | |
257 } | |
258 | |
259 void CalculateRectTransforms(const gfx::Size& desired_size, | |
260 float corner_radius, | |
261 PaintedShapeTransforms* transforms_out) const { | |
262 DCHECK_GE(desired_size.width() / 2.0f, corner_radius) | |
263 << "The circle's diameter should not be greater than the total width."; | |
264 DCHECK_GE(desired_size.height() / 2.0f, corner_radius) | |
265 << "The circle's diameter should not be greater than the total height."; | |
266 | |
267 gfx::SizeF size(desired_size); | |
268 // This function can be called before the layer's been added to a view, | |
269 // either at construction time or in tests. | |
270 if (GetCompositor()) { | |
271 // Modify |desired_size| so that the ripple aligns to pixel bounds. | |
272 const float dsf = GetCompositor()->device_scale_factor(); | |
273 gfx::RectF ripple_bounds((gfx::PointF(center_point_)), gfx::SizeF()); | |
274 ripple_bounds.Inset(-gfx::InsetsF(desired_size.height() / 2.0f, | |
275 desired_size.width() / 2.0f)); | |
276 ripple_bounds.Scale(dsf); | |
277 ripple_bounds = gfx::RectF(gfx::ToEnclosingRect(ripple_bounds)); | |
278 ripple_bounds.Scale(1.0f / dsf); | |
279 size = ripple_bounds.size(); | |
280 } | |
281 | |
282 // The shapes are drawn such that their center points are not at the origin. | |
283 // Thus we use the CalculateCircleTransform() and CalculateRectTransform() | |
284 // methods to calculate the complex Transforms. | |
285 | |
286 const float circle_scale = std::max( | |
287 kMinimumCircleScale, | |
288 corner_radius / static_cast<float>(circle_layer_delegate_->radius())); | |
289 | |
290 const float circle_target_x_offset = size.width() / 2.0f - corner_radius; | |
291 const float circle_target_y_offset = size.height() / 2.0f - corner_radius; | |
292 | |
293 (*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform( | |
294 circle_scale, -circle_target_x_offset, -circle_target_y_offset); | |
295 (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform( | |
296 circle_scale, circle_target_x_offset, -circle_target_y_offset); | |
297 (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform( | |
298 circle_scale, circle_target_x_offset, circle_target_y_offset); | |
299 (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform( | |
300 circle_scale, -circle_target_x_offset, circle_target_y_offset); | |
301 | |
302 const float rect_delegate_width = rect_layer_delegate_->size().width(); | |
303 const float rect_delegate_height = rect_layer_delegate_->size().height(); | |
304 | |
305 (*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform( | |
306 std::max(kMinimumRectScale, size.width() / rect_delegate_width), | |
307 std::max(kMinimumRectScale, (size.height() - 2.0f * corner_radius) / | |
308 rect_delegate_height)); | |
309 | |
310 (*transforms_out)[VERTICAL_RECT] = CalculateRectTransform( | |
311 std::max(kMinimumRectScale, | |
312 (size.width() - 2.0f * corner_radius) / rect_delegate_width), | |
313 std::max(kMinimumRectScale, size.height() / rect_delegate_height)); | |
314 } | |
315 | |
316 gfx::Transform CalculateCircleTransform(float scale, | |
317 float target_center_x, | |
318 float target_center_y) const { | |
319 gfx::Transform transform; | |
320 // Offset for the center point of the ripple. | |
321 transform.Translate(center_point_.x(), center_point_.y()); | |
322 // Move circle to target. | |
323 transform.Translate(target_center_x, target_center_y); | |
324 transform.Scale(scale, scale); | |
325 // Align center point of the painted circle. | |
326 const gfx::Vector2dF circle_center_offset = | |
327 circle_layer_delegate_->GetCenteringOffset(); | |
328 transform.Translate(-circle_center_offset.x(), -circle_center_offset.y()); | |
329 return transform; | |
330 } | |
331 | |
332 gfx::Transform CalculateRectTransform(float x_scale, float y_scale) const { | |
333 gfx::Transform transform; | |
334 transform.Translate(center_point_.x(), center_point_.y()); | |
335 transform.Scale(x_scale, y_scale); | |
336 const gfx::Vector2dF rect_center_offset = | |
337 rect_layer_delegate_->GetCenteringOffset(); | |
338 transform.Translate(-rect_center_offset.x(), -rect_center_offset.y()); | |
339 return transform; | |
340 } | |
341 | |
342 void AnimateToTransforms( | |
343 const PaintedShapeTransforms transforms, | |
344 base::TimeDelta duration, | |
345 ui::LayerAnimator::PreemptionStrategy preemption_strategy, | |
346 gfx::Tween::Type tween, | |
347 ui::LayerAnimationObserver* animation_observer) { | |
348 for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) { | |
349 ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator(); | |
350 ui::ScopedLayerAnimationSettings animation(animator); | |
351 animation.SetPreemptionStrategy(preemption_strategy); | |
352 animation.SetTweenType(tween); | |
353 std::unique_ptr<ui::LayerAnimationElement> element = | |
354 ui::LayerAnimationElement::CreateTransformElement(transforms[i], | |
355 duration); | |
oshima
2017/07/06 19:23:55
so just setting transform didn't work?
xiaohuic
2017/07/06 20:55:41
It should work. It's more about supporting LayerA
oshima
2017/07/06 22:04:42
will animator->AddObserver(animation_observer) wor
xc
2017/07/07 16:38:14
It causes a crash. I think it requires the caller
oshima
2017/07/07 19:15:36
I see, looks like CallbackLayerAnimatorObserver is
xc
2017/07/07 23:35:39
Acknowledged.
| |
356 ui::LayerAnimationSequence* sequence = | |
357 new ui::LayerAnimationSequence(std::move(element)); | |
358 | |
359 if (animation_observer) | |
360 sequence->AddObserver(animation_observer); | |
361 | |
362 animator->StartAnimation(sequence); | |
363 } | |
364 } | |
365 | |
366 std::string ToLayerName(PaintedShape painted_shape) { | |
367 switch (painted_shape) { | |
368 case TOP_LEFT_CIRCLE: | |
369 return "TOP_LEFT_CIRCLE"; | |
370 case TOP_RIGHT_CIRCLE: | |
371 return "TOP_RIGHT_CIRCLE"; | |
372 case BOTTOM_RIGHT_CIRCLE: | |
373 return "BOTTOM_RIGHT_CIRCLE"; | |
374 case BOTTOM_LEFT_CIRCLE: | |
375 return "BOTTOM_LEFT_CIRCLE"; | |
376 case HORIZONTAL_RECT: | |
377 return "HORIZONTAL_RECT"; | |
378 case VERTICAL_RECT: | |
379 return "VERTICAL_RECT"; | |
380 case PAINTED_SHAPE_COUNT: | |
381 NOTREACHED() << "The PAINTED_SHAPE_COUNT value should never be used."; | |
382 return "PAINTED_SHAPE_COUNT"; | |
383 } | |
384 return "UNKNOWN"; | |
385 } | |
386 | |
104 void OnPaintLayer(const ui::PaintContext& context) override { | 387 void OnPaintLayer(const ui::PaintContext& context) override { |
105 // Radius is based on the parent layer size, the shadow layer is expanded | 388 // Radius is based on the parent layer size, the shadow layer is expanded |
106 // to make room for the shadow. | 389 // to make room for the shadow. |
107 float radius = size().width() / 2.f; | 390 float radius = size().width() / 2.f; |
108 | 391 |
109 ui::PaintRecorder recorder(context, shadow_layer_->size()); | 392 ui::PaintRecorder recorder(context, shadow_layer_->size()); |
110 gfx::Canvas* canvas = recorder.canvas(); | 393 gfx::Canvas* canvas = recorder.canvas(); |
111 | 394 |
112 cc::PaintFlags flags; | 395 cc::PaintFlags flags; |
113 flags.setColor(SK_ColorWHITE); | 396 flags.setColor(SK_ColorWHITE); |
114 flags.setAntiAlias(true); | 397 flags.setAntiAlias(true); |
115 flags.setStyle(cc::PaintFlags::kFill_Style); | 398 flags.setStyle(cc::PaintFlags::kFill_Style); |
116 flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_)); | 399 flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_)); |
117 gfx::Rect shadow_bounds = shadow_layer_->bounds(); | 400 gfx::Rect shadow_bounds = shadow_layer_->bounds(); |
118 canvas->DrawCircle( | 401 canvas->DrawCircle( |
119 gfx::PointF(radius - shadow_bounds.x(), radius - shadow_bounds.y()), | 402 gfx::PointF(radius - shadow_bounds.x(), radius - shadow_bounds.y()), |
120 radius, flags); | 403 radius, flags); |
121 } | 404 } |
122 | 405 |
123 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} | 406 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} |
124 | 407 |
125 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} | 408 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} |
126 | 409 |
410 // ui::Layers for all of the painted shape layers that compose the morphing | |
411 // shape. | |
412 std::unique_ptr<ui::Layer> painted_layers_[PAINTED_SHAPE_COUNT]; | |
413 | |
414 const gfx::Size large_size_; | |
415 | |
416 const gfx::Size small_size_; | |
417 | |
418 // The center point of the painted shape. | |
419 gfx::PointF center_point_; | |
420 | |
421 // ui::LayerDelegate to paint circles for all the circle layers. | |
422 std::unique_ptr<views::CircleLayerDelegate> circle_layer_delegate_; | |
423 | |
424 // ui::LayerDelegate to paint rectangles for all the rectangle layers. | |
425 std::unique_ptr<views::RectangleLayerDelegate> rect_layer_delegate_; | |
426 | |
127 gfx::ShadowValues shadow_values_; | 427 gfx::ShadowValues shadow_values_; |
128 | 428 |
129 std::unique_ptr<ui::Layer> shadow_layer_; | 429 std::unique_ptr<ui::Layer> shadow_layer_; |
130 | 430 |
131 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIconBackground); | 431 DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIconBackground); |
132 }; | 432 }; |
133 | 433 |
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) | 434 VoiceInteractionOverlay::VoiceInteractionOverlay(AppListButton* host_view) |
160 : ripple_layer_(new ui::Layer()), | 435 : ripple_layer_(new ui::Layer()), |
161 icon_layer_(new VoiceInteractionIcon()), | 436 icon_layer_(new VoiceInteractionIcon()), |
162 background_layer_(new VoiceInteractionIconBackground()), | 437 background_layer_(new VoiceInteractionIconBackground()), |
163 host_view_(host_view), | 438 host_view_(host_view), |
164 is_bursting_(false), | 439 is_bursting_(false), |
165 circle_layer_delegate_(kRippleColor, kRippleCircleInitRadiusDip) { | 440 circle_layer_delegate_(kRippleColor, kRippleCircleInitRadiusDip) { |
166 SetPaintToLayer(ui::LAYER_NOT_DRAWN); | 441 SetPaintToLayer(ui::LAYER_NOT_DRAWN); |
167 layer()->set_name("VoiceInteractionOverlay:ROOT_LAYER"); | 442 layer()->set_name("VoiceInteractionOverlay:ROOT_LAYER"); |
168 layer()->SetMasksToBounds(false); | 443 layer()->SetMasksToBounds(false); |
169 | 444 |
170 ripple_layer_->SetBounds(gfx::Rect(0, 0, kRippleCircleInitRadiusDip * 2, | 445 ripple_layer_->SetBounds(gfx::Rect(0, 0, kRippleCircleInitRadiusDip * 2, |
171 kRippleCircleInitRadiusDip * 2)); | 446 kRippleCircleInitRadiusDip * 2)); |
172 ripple_layer_->set_delegate(&circle_layer_delegate_); | 447 ripple_layer_->set_delegate(&circle_layer_delegate_); |
173 ripple_layer_->SetFillsBoundsOpaquely(false); | 448 ripple_layer_->SetFillsBoundsOpaquely(false); |
174 ripple_layer_->SetMasksToBounds(true); | 449 ripple_layer_->SetMasksToBounds(true); |
175 ripple_layer_->set_name("VoiceInteractionOverlay:PAINTED_LAYER"); | 450 ripple_layer_->set_name("VoiceInteractionOverlay:PAINTED_LAYER"); |
176 layer()->Add(ripple_layer_.get()); | 451 layer()->Add(ripple_layer_.get()); |
177 | 452 |
178 layer()->Add(background_layer_.get()); | 453 layer()->Add(background_layer_.get()); |
179 | 454 |
180 layer()->Add(icon_layer_.get()); | 455 layer()->Add(icon_layer_.get()); |
181 } | 456 } |
182 | 457 |
183 VoiceInteractionOverlay::~VoiceInteractionOverlay() {} | 458 VoiceInteractionOverlay::~VoiceInteractionOverlay() {} |
184 | 459 |
185 void VoiceInteractionOverlay::StartAnimation() { | 460 void VoiceInteractionOverlay::StartAnimation(bool show_icon) { |
186 is_bursting_ = false; | 461 is_bursting_ = false; |
462 show_icon_ = show_icon; | |
187 SetVisible(true); | 463 SetVisible(true); |
188 | 464 |
189 // Setup ripple initial state. | 465 // Setup ripple initial state. |
190 ripple_layer_->SetOpacity(0); | 466 ripple_layer_->SetOpacity(0); |
191 | 467 |
192 SkMScalar scale_factor = | 468 SkMScalar scale_factor = |
193 kRippleCircleStartRadiusDip / kRippleCircleInitRadiusDip; | 469 kRippleCircleStartRadiusDip / kRippleCircleInitRadiusDip; |
194 gfx::Transform transform; | 470 gfx::Transform transform; |
195 | 471 |
196 const gfx::Point center = host_view_->GetCenterPoint(); | 472 const gfx::Point center = host_view_->GetCenterPoint(); |
(...skipping 15 matching lines...) Expand all Loading... | |
212 base::TimeDelta::FromMilliseconds(kRippleExpandDurationMs)); | 488 base::TimeDelta::FromMilliseconds(kRippleExpandDurationMs)); |
213 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); | 489 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); |
214 | 490 |
215 ripple_layer_->SetTransform(transform); | 491 ripple_layer_->SetTransform(transform); |
216 | 492 |
217 settings.SetTransitionDuration( | 493 settings.SetTransitionDuration( |
218 base::TimeDelta::FromMilliseconds(kRippleOpacityDurationMs)); | 494 base::TimeDelta::FromMilliseconds(kRippleOpacityDurationMs)); |
219 ripple_layer_->SetOpacity(kRippleOpacity); | 495 ripple_layer_->SetOpacity(kRippleOpacity); |
220 } | 496 } |
221 | 497 |
222 // We need to determine the animation direction based on shelf alignment. | 498 icon_layer_->SetOpacity(0); |
223 ShelfAlignment alignment = | 499 background_layer_->SetOpacity(0); |
224 Shelf::ForWindow(host_view_->GetWidget()->GetNativeWindow())->alignment(); | 500 if (!show_icon_) |
501 return; | |
225 | 502 |
226 // Setup icon initial state. | 503 // Setup icon initial state. |
227 icon_layer_->SetOpacity(0); | |
228 transform.MakeIdentity(); | 504 transform.MakeIdentity(); |
229 | |
230 transform.Translate(center.x() - kIconStartSizeDip / 2.f, | 505 transform.Translate(center.x() - kIconStartSizeDip / 2.f, |
231 center.y() - kIconStartSizeDip / 2.f); | 506 center.y() - kIconStartSizeDip / 2.f); |
232 | 507 |
233 scale_factor = kIconStartSizeDip / kIconInitSizeDip; | 508 scale_factor = kIconStartSizeDip / kIconInitSizeDip; |
234 transform.Scale(scale_factor, scale_factor); | 509 transform.Scale(scale_factor, scale_factor); |
235 icon_layer_->SetTransform(transform); | 510 icon_layer_->SetTransform(transform); |
236 | 511 |
237 // Setup icon animation. | 512 // Setup icon animation. |
238 scale_factor = kIconSizeDip / kIconInitSizeDip; | 513 scale_factor = kIconSizeDip / kIconInitSizeDip; |
239 transform.MakeIdentity(); | 514 transform.MakeIdentity(); |
240 if (alignment == SHELF_ALIGNMENT_BOTTOM || | 515 transform.Translate(center.x() - kIconSizeDip / 2 + kIconOffsetDip, |
241 alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) { | 516 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); | 517 transform.Scale(scale_factor, scale_factor); |
253 | 518 |
254 { | 519 { |
255 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); | 520 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); |
256 settings.SetTransitionDuration( | 521 settings.SetTransitionDuration( |
257 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs)); | 522 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs)); |
258 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); | 523 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); |
259 | 524 |
260 icon_layer_->SetTransform(transform); | 525 icon_layer_->SetTransform(transform); |
261 icon_layer_->SetOpacity(kIconOpacity); | 526 icon_layer_->SetOpacity(kIconOpacity); |
262 } | 527 } |
263 | 528 |
264 // Setup background initial state. | 529 // Setup background initial state. |
265 background_layer_->SetOpacity(0); | 530 background_layer_->ResetShape(); |
266 | 531 |
267 transform.MakeIdentity(); | 532 transform.MakeIdentity(); |
268 transform.Translate(center.x() - kBackgroundStartSizeDip / 2.f, | 533 transform.Translate(center.x() - kBackgroundStartSizeDip / 2.f, |
269 center.y() - kBackgroundStartSizeDip / 2.f); | 534 center.y() - kBackgroundStartSizeDip / 2.f); |
270 | 535 |
271 scale_factor = kBackgroundStartSizeDip / kBackgroundInitSizeDip; | 536 scale_factor = kBackgroundStartSizeDip / kBackgroundInitSizeDip; |
272 transform.Scale(scale_factor, scale_factor); | 537 transform.Scale(scale_factor, scale_factor); |
273 background_layer_->SetTransform(transform); | 538 background_layer_->SetTransform(transform); |
274 | 539 |
275 // Setup background animation. | 540 // Setup background animation. |
276 scale_factor = kBackgroundSizeDip / kBackgroundInitSizeDip; | 541 scale_factor = kBackgroundSizeDip / kBackgroundInitSizeDip; |
277 transform.MakeIdentity(); | 542 transform.MakeIdentity(); |
278 if (alignment == SHELF_ALIGNMENT_BOTTOM || | 543 transform.Translate(center.x() - kBackgroundSizeDip / 2 + kIconOffsetDip, |
279 alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) { | 544 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); | 545 transform.Scale(scale_factor, scale_factor); |
291 | 546 |
292 { | 547 { |
293 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); | 548 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); |
294 settings.SetTransitionDuration( | 549 settings.SetTransitionDuration( |
295 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs)); | 550 base::TimeDelta::FromMilliseconds(kFullExpandDurationMs)); |
296 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); | 551 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); |
297 | 552 |
298 background_layer_->SetTransform(transform); | 553 background_layer_->SetTransform(transform); |
299 } | 554 } |
300 | 555 |
301 { | 556 { |
302 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); | 557 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); |
303 settings.SetTransitionDuration( | 558 settings.SetTransitionDuration( |
304 base::TimeDelta::FromMilliseconds(kBackgroundOpacityDurationMs)); | 559 base::TimeDelta::FromMilliseconds(kBackgroundOpacityDurationMs)); |
305 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); | 560 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_2); |
306 | 561 |
307 background_layer_->SetOpacity(1); | 562 background_layer_->SetOpacity(1); |
308 } | 563 } |
309 } | 564 } |
310 | 565 |
311 void VoiceInteractionOverlay::BurstAnimation() { | 566 void VoiceInteractionOverlay::BurstAnimation() { |
312 is_bursting_ = true; | 567 is_bursting_ = true; |
568 should_hide_animation_ = false; | |
313 | 569 |
314 gfx::Point center = host_view_->GetCenterPoint(); | 570 gfx::Point center = host_view_->GetCenterPoint(); |
571 gfx::Transform transform; | |
315 | 572 |
316 // Setup ripple animations. | 573 // Setup ripple animations. |
317 { | 574 { |
318 SkMScalar scale_factor = | 575 SkMScalar scale_factor = |
319 kRippleCircleBurstRadiusDip / kRippleCircleInitRadiusDip; | 576 kRippleCircleBurstRadiusDip / kRippleCircleInitRadiusDip; |
320 std::unique_ptr<gfx::Transform> transform(new gfx::Transform()); | 577 transform.Translate(center.x() - kRippleCircleBurstRadiusDip, |
321 transform->Translate(center.x() - kRippleCircleBurstRadiusDip, | 578 center.y() - kRippleCircleBurstRadiusDip); |
322 center.y() - kRippleCircleBurstRadiusDip); | 579 transform.Scale(scale_factor, scale_factor); |
323 transform->Scale(scale_factor, scale_factor); | |
324 | 580 |
325 ui::ScopedLayerAnimationSettings settings(ripple_layer_->GetAnimator()); | 581 ui::ScopedLayerAnimationSettings settings(ripple_layer_->GetAnimator()); |
326 settings.SetTransitionDuration( | 582 settings.SetTransitionDuration( |
327 base::TimeDelta::FromMilliseconds(kFullBurstDurationMs)); | 583 base::TimeDelta::FromMilliseconds(kFullBurstDurationMs)); |
328 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | 584 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); |
585 settings.SetPreemptionStrategy( | |
586 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); | |
329 | 587 |
330 ripple_layer_->SetTransform(*transform.get()); | 588 ripple_layer_->SetTransform(transform); |
331 ripple_layer_->SetOpacity(0); | 589 ripple_layer_->SetOpacity(0); |
332 } | 590 } |
333 | 591 |
592 if (!show_icon_) | |
593 return; | |
594 | |
334 // Setup icon animation. | 595 // Setup icon animation. |
335 { | 596 { |
336 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); | 597 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); |
337 settings.SetTransitionDuration( | 598 settings.SetTransitionDuration( |
338 base::TimeDelta::FromMilliseconds(kIconBurstDurationMs)); | 599 base::TimeDelta::FromMilliseconds(kBackgroundMorphDurationMs)); |
600 settings.SetPreemptionStrategy( | |
601 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); | |
339 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | 602 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); |
340 | 603 |
341 icon_layer_->SetOpacity(0); | 604 transform.MakeIdentity(); |
605 transform.Translate(kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip - | |
606 kIconEndSizeDip / 2, | |
607 -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip - | |
608 kIconEndSizeDip / 2); | |
609 SkMScalar scale_factor = kIconEndSizeDip / kIconInitSizeDip; | |
610 transform.Scale(scale_factor, scale_factor); | |
611 | |
612 icon_layer_->SetTransform(transform); | |
342 } | 613 } |
343 | 614 |
344 // Setup background animation. | 615 // Setup background animation. |
345 { | 616 ui::CallbackLayerAnimationObserver* observer = |
346 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); | 617 new ui::CallbackLayerAnimationObserver( |
347 settings.SetTransitionDuration( | 618 base::Bind(&VoiceInteractionOverlay::AnimationEndedCallback, |
348 base::TimeDelta::FromMilliseconds(kIconBurstDurationMs)); | 619 base::Unretained(this))); |
349 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | 620 // Transform to new shape. |
621 // We want to animate from the background's current position into a larger | |
622 // size. The animation moves the background's center point while morphing from | |
623 // circle to a rectangle. | |
624 float x_offset = center.x() - kBackgroundSizeDip / 2 + kIconOffsetDip; | |
625 float y_offset = center.y() - kBackgroundSizeDip / 2 - kIconOffsetDip; | |
350 | 626 |
351 background_layer_->SetOpacity(0); | 627 background_layer_->AnimateToLarge( |
352 } | 628 gfx::PointF( |
629 kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip - x_offset, | |
630 -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip - y_offset), | |
631 observer); | |
632 observer->SetActive(); | |
353 } | 633 } |
354 | 634 |
355 void VoiceInteractionOverlay::EndAnimation() { | 635 void VoiceInteractionOverlay::EndAnimation() { |
356 if (is_bursting_) { | 636 if (is_bursting_) { |
357 // Too late, user action already fired, we have to finish what's started. | 637 // Too late, user action already fired, we have to finish what's started. |
358 return; | 638 return; |
359 } | 639 } |
360 | 640 |
361 // Play reverse animation | 641 // Play reverse animation |
362 // Setup ripple animations. | 642 // Setup ripple animations. |
(...skipping 14 matching lines...) Expand all Loading... | |
377 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs)); | 657 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs)); |
378 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN); | 658 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN); |
379 | 659 |
380 ripple_layer_->SetTransform(transform); | 660 ripple_layer_->SetTransform(transform); |
381 | 661 |
382 settings.SetTransitionDuration( | 662 settings.SetTransitionDuration( |
383 base::TimeDelta::FromMilliseconds(kRippleOpacityRetractDurationMs)); | 663 base::TimeDelta::FromMilliseconds(kRippleOpacityRetractDurationMs)); |
384 ripple_layer_->SetOpacity(0); | 664 ripple_layer_->SetOpacity(0); |
385 } | 665 } |
386 | 666 |
667 if (!show_icon_) | |
668 return; | |
669 | |
387 // Setup icon animation. | 670 // Setup icon animation. |
388 transform.MakeIdentity(); | 671 transform.MakeIdentity(); |
389 | 672 |
390 transform.Translate(center.x() - kIconStartSizeDip / 2.f, | 673 transform.Translate(center.x() - kIconStartSizeDip / 2.f, |
391 center.y() - kIconStartSizeDip / 2.f); | 674 center.y() - kIconStartSizeDip / 2.f); |
392 | 675 |
393 scale_factor = kIconStartSizeDip / kIconInitSizeDip; | 676 scale_factor = kIconStartSizeDip / kIconInitSizeDip; |
394 transform.Scale(scale_factor, scale_factor); | 677 transform.Scale(scale_factor, scale_factor); |
395 | 678 |
396 { | 679 { |
(...skipping 23 matching lines...) Expand all Loading... | |
420 IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 703 IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
421 settings.SetTransitionDuration( | 704 settings.SetTransitionDuration( |
422 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs)); | 705 base::TimeDelta::FromMilliseconds(kFullRetractDurationMs)); |
423 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN); | 706 settings.SetTweenType(gfx::Tween::SLOW_OUT_LINEAR_IN); |
424 | 707 |
425 background_layer_->SetTransform(transform); | 708 background_layer_->SetTransform(transform); |
426 background_layer_->SetOpacity(0); | 709 background_layer_->SetOpacity(0); |
427 } | 710 } |
428 } | 711 } |
429 | 712 |
713 void VoiceInteractionOverlay::HideAnimation() { | |
714 is_bursting_ = false; | |
715 | |
716 should_hide_animation_ = true; | |
717 if (background_layer_->GetAnimator()->is_animating()) { | |
718 // Wait for current animation to finish | |
719 return; | |
720 } | |
721 | |
722 // Setup ripple animations. | |
723 { | |
724 ui::ScopedLayerAnimationSettings settings(ripple_layer_->GetAnimator()); | |
725 settings.SetTransitionDuration( | |
726 base::TimeDelta::FromMilliseconds(kHideDurationMs)); | |
727 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | |
728 settings.SetPreemptionStrategy( | |
729 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); | |
730 | |
731 ripple_layer_->SetOpacity(0); | |
732 } | |
733 | |
734 // Setup icon animation. | |
735 { | |
736 ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); | |
737 settings.SetTransitionDuration( | |
738 base::TimeDelta::FromMilliseconds(kHideDurationMs)); | |
739 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | |
740 settings.SetPreemptionStrategy( | |
741 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); | |
742 | |
743 icon_layer_->SetOpacity(0); | |
744 } | |
745 | |
746 // Setup background animation. | |
747 { | |
748 ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); | |
749 settings.SetTransitionDuration( | |
750 base::TimeDelta::FromMilliseconds(kHideDurationMs)); | |
751 settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | |
752 settings.SetPreemptionStrategy( | |
753 ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); | |
754 | |
755 background_layer_->SetOpacity(0); | |
756 } | |
757 } | |
758 | |
759 bool VoiceInteractionOverlay::AnimationEndedCallback( | |
760 const ui::CallbackLayerAnimationObserver& observer) { | |
761 if (should_hide_animation_) | |
762 HideAnimation(); | |
763 | |
764 return true; | |
765 } | |
766 | |
430 } // namespace ash | 767 } // namespace ash |
OLD | NEW |