1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/layout/layout_property.h"
17 #include "date_time_animation_controller.h"
18
19 namespace OHOS::Ace::NG {
20 namespace {
21 constexpr int32_t CHILD_SIZE = 3;
22 constexpr double SEMI_CIRCLE_ANGEL = 180;
23 constexpr double OPACITY_DELAY = 100;
24 constexpr double COLUMN_OPACITY_DELAY = 150;
25 constexpr double OPACITY_DURATION = 150;
26 constexpr double TRIANGLE_DURATION = 300;
27 constexpr double MOVE_DURATION = 500;
28 } // namespace
PlayTitleInAnimation()29 void DateTimeAnimationController::PlayTitleInAnimation()
30 {
31 CHECK_NULL_VOID(buttonIcon_);
32 auto renderContext = buttonIcon_->GetRenderContext();
33 AnimationOption animationOption;
34 animationOption.SetDuration(TRIANGLE_DURATION);
35 animationOption.SetCurve(Curves::SHARP);
36
37 renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0, 0));
38 AnimationUtils::Animate(animationOption,
39 [renderContext]() {
40 CHECK_NULL_VOID_NOLOG(renderContext);
41 renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0 - SEMI_CIRCLE_ANGEL, 0));
42 });
43 }
44
PlayTitleOutAnimation()45 void DateTimeAnimationController::PlayTitleOutAnimation()
46 {
47 CHECK_NULL_VOID(buttonIcon_);
48 auto renderContext = buttonIcon_->GetRenderContext();
49 AnimationOption animationOption;
50 animationOption.SetDuration(TRIANGLE_DURATION);
51 animationOption.SetCurve(Curves::SHARP);
52
53 renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0 - SEMI_CIRCLE_ANGEL, 0));
54 AnimationUtils::Animate(animationOption,
55 [renderContext]() {
56 CHECK_NULL_VOID_NOLOG(renderContext);
57 renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0, 0));
58 });
59 }
60
PlayMovingInAnimation()61 void DateTimeAnimationController::PlayMovingInAnimation()
62 {
63 CHECK_NULL_VOID(year_);
64 CHECK_NULL_VOID(month_);
65 CHECK_NULL_VOID(day_);
66 auto yearRenderContext = year_->GetRenderContext();
67 auto monthRenderContext = month_->GetRenderContext();
68 auto dayRenderContext = day_->GetRenderContext();
69 AnimationOption animationOption;
70 animationOption.SetDuration(MOVE_DURATION);
71 animationOption.SetCurve(Curves::FRICTION);
72
73 yearRenderContext->UpdateTransformTranslate({ yearStart_, 0.0f, 0.0f });
74 monthRenderContext->UpdateTransformTranslate({ monthStart_, 0.0f, 0.0f });
75 dayRenderContext->UpdateTransformTranslate({ dayStart_, 0.0f, 0.0f });
76 AnimationUtils::Animate(animationOption,
77 [yearRenderContext, monthRenderContext, dayRenderContext, weak = AceType::WeakClaim(this)]() {
78 auto ref = weak.Upgrade();
79 CHECK_NULL_VOID(ref);
80 CHECK_NULL_VOID_NOLOG(yearRenderContext);
81 CHECK_NULL_VOID_NOLOG(monthRenderContext);
82 CHECK_NULL_VOID_NOLOG(dayRenderContext);
83 yearRenderContext->UpdateTransformTranslate({ ref->yearEnd_, 0.0f, 0.0f });
84 monthRenderContext->UpdateTransformTranslate({ ref->monthEnd_, 0.0f, 0.0f });
85 dayRenderContext->UpdateTransformTranslate({ ref->dayEnd_, 0.0f, 0.0f });
86 });
87 }
88
PlayMovingOutAnimation()89 void DateTimeAnimationController::PlayMovingOutAnimation()
90 {
91 CHECK_NULL_VOID(year_);
92 CHECK_NULL_VOID(month_);
93 CHECK_NULL_VOID(day_);
94 auto yearRenderContext = year_->GetRenderContext();
95 auto monthRenderContext = month_->GetRenderContext();
96 auto dayRenderContext = day_->GetRenderContext();
97 AnimationOption animationOption;
98 animationOption.SetDuration(MOVE_DURATION);
99 animationOption.SetCurve(Curves::FRICTION);
100
101 yearRenderContext->UpdateTransformTranslate({ yearEnd_, 0.0f, 0.0f });
102 monthRenderContext->UpdateTransformTranslate({ monthEnd_, 0.0f, 0.0f });
103 dayRenderContext->UpdateTransformTranslate({ dayEnd_, 0.0f, 0.0f });
104 AnimationUtils::Animate(animationOption,
105 [yearRenderContext, monthRenderContext, dayRenderContext, weak = AceType::WeakClaim(this)]() {
106 auto ref = weak.Upgrade();
107 CHECK_NULL_VOID(ref);
108 CHECK_NULL_VOID_NOLOG(yearRenderContext);
109 CHECK_NULL_VOID_NOLOG(monthRenderContext);
110 CHECK_NULL_VOID_NOLOG(dayRenderContext);
111 yearRenderContext->UpdateTransformTranslate({ ref->yearStart_, 0.0f, 0.0f });
112 monthRenderContext->UpdateTransformTranslate({ ref->monthStart_, 0.0f, 0.0f });
113 dayRenderContext->UpdateTransformTranslate({ ref->dayStart_, 0.0f, 0.0f });
114 });
115 }
116
PlayOldColumnOpacityInAnimation()117 void DateTimeAnimationController::PlayOldColumnOpacityInAnimation()
118 {
119 CHECK_NULL_VOID(monthDays_);
120 CHECK_NULL_VOID(timePicker_);
121 auto monthDaysRender = monthDays_->GetRenderContext();
122 auto timePickerRender = timePicker_->GetRenderContext();
123 CHECK_NULL_VOID(monthDaysRender);
124 CHECK_NULL_VOID(timePickerRender);
125 if (datePicker_) {
126 auto layoutProperty = datePicker_->GetLayoutProperty<LayoutProperty>();
127 if (layoutProperty) {
128 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
129 }
130 }
131 AnimationOption animationOption;
132 animationOption.SetDuration(OPACITY_DURATION);
133 animationOption.SetCurve(Curves::LINEAR);
134 animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
135 auto ref = weak.Upgrade();
136 CHECK_NULL_VOID(ref);
137 if (ref->isOutAnimationPlaying_) {
138 ref->isInAnimationPlaying_ = false;
139 return;
140 }
141 auto monthDaysNode = ref->monthDays_;
142 CHECK_NULL_VOID(monthDaysNode);
143 auto layoutProperty = monthDaysNode->GetLayoutProperty<LayoutProperty>();
144 CHECK_NULL_VOID(layoutProperty);
145 layoutProperty->UpdateVisibility(VisibleType::GONE);
146
147 auto timePickerNode = ref->timePicker_;
148 CHECK_NULL_VOID(timePickerNode);
149 layoutProperty = timePickerNode->GetLayoutProperty<LayoutProperty>();
150 CHECK_NULL_VOID(layoutProperty);
151 layoutProperty->UpdateVisibility(VisibleType::GONE);
152 ref->isInAnimationPlaying_ = false;
153 });
154 monthDaysRender->UpdateOpacity(1);
155 timePickerRender->UpdateOpacity(1);
156 oldColumnOpacityInAnimation_ = AnimationUtils::StartAnimation(animationOption,
157 [monthDaysRender, timePickerRender]() {
158 CHECK_NULL_VOID_NOLOG(monthDaysRender);
159 CHECK_NULL_VOID_NOLOG(timePickerRender);
160 monthDaysRender->UpdateOpacity(0);
161 timePickerRender->UpdateOpacity(0);
162 }, animationOption.GetOnFinishEvent());
163 }
164
PlayNewColumnOpacityInAnimation()165 void DateTimeAnimationController::PlayNewColumnOpacityInAnimation()
166 {
167 CHECK_NULL_VOID(month_);
168 CHECK_NULL_VOID(day_);
169 auto monthRender = month_->GetRenderContext();
170 auto dayRender = day_->GetRenderContext();
171 CHECK_NULL_VOID(monthRender);
172 CHECK_NULL_VOID(dayRender);
173
174 AnimationOption animationOption;
175 animationOption.SetDuration(OPACITY_DURATION);
176 animationOption.SetCurve(Curves::LINEAR);
177
178 monthRender->UpdateOpacity(0);
179 dayRender->UpdateOpacity(0);
180 AnimationUtils::Animate(animationOption,
181 [monthRender, dayRender]() {
182 CHECK_NULL_VOID_NOLOG(monthRender);
183 CHECK_NULL_VOID_NOLOG(dayRender);
184 monthRender->UpdateOpacity(1);
185 dayRender->UpdateOpacity(1);
186 });
187 }
188
PlayYearColumnOpacityInAnimation()189 void DateTimeAnimationController::PlayYearColumnOpacityInAnimation()
190 {
191 CHECK_NULL_VOID(year_);
192 auto yearRender = year_->GetRenderContext();
193 CHECK_NULL_VOID(yearRender);
194
195 AnimationOption animationOption;
196 animationOption.SetDelay(OPACITY_DELAY);
197 animationOption.SetDuration(OPACITY_DURATION);
198 animationOption.SetCurve(Curves::LINEAR);
199
200 yearRender->OpacityAnimation(animationOption, 0.0f, 1.0f);
201 }
202
PlayButtonOpacityInAnimation()203 void DateTimeAnimationController::PlayButtonOpacityInAnimation()
204 {
205 CHECK_NULL_VOID(buttonRow_);
206 auto buttonRender = buttonRow_->GetRenderContext();
207 CHECK_NULL_VOID(buttonRender);
208
209 AnimationOption animationOption;
210 animationOption.SetDelay(OPACITY_DELAY);
211 animationOption.SetDuration(OPACITY_DURATION);
212 animationOption.SetCurve(Curves::LINEAR);
213 animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
214 auto ref = weak.Upgrade();
215 CHECK_NULL_VOID(ref);
216 auto buttonNode = ref->buttonRow_;
217 CHECK_NULL_VOID(buttonNode);
218 auto layoutProperty = buttonNode->GetLayoutProperty<LayoutProperty>();
219 CHECK_NULL_VOID(layoutProperty);
220 layoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
221 auto focusHub = buttonNode->GetFocusHub();
222 CHECK_NULL_VOID(focusHub);
223 focusHub->SetShow(false);
224 });
225 buttonRender->OpacityAnimation(animationOption, 1.0f, 0.0f);
226 }
227
PlayOldColumnOpacityOutAnimation()228 void DateTimeAnimationController::PlayOldColumnOpacityOutAnimation()
229 {
230 CHECK_NULL_VOID(monthDays_);
231 auto monthDaysRender = monthDays_->GetRenderContext();
232 CHECK_NULL_VOID(timePicker_);
233 auto timePickerRender = timePicker_->GetRenderContext();
234
235 auto layoutProperty = monthDays_->GetLayoutProperty<LayoutProperty>();
236 CHECK_NULL_VOID(layoutProperty);
237 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
238 layoutProperty = timePicker_->GetLayoutProperty<LayoutProperty>();
239 CHECK_NULL_VOID(layoutProperty);
240 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
241
242 AnimationOption animationOption;
243 animationOption.SetDelay(COLUMN_OPACITY_DELAY);
244 animationOption.SetDuration(OPACITY_DURATION);
245 animationOption.SetCurve(Curves::LINEAR);
246 animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
247 auto ref = weak.Upgrade();
248 CHECK_NULL_VOID(ref);
249 if (ref->isInAnimationPlaying_) {
250 ref->isOutAnimationPlaying_ = false;
251 return;
252 }
253 auto datePickerNode = ref->datePicker_;
254 CHECK_NULL_VOID(datePickerNode);
255 auto layoutProperty = datePickerNode->GetLayoutProperty<LayoutProperty>();
256 CHECK_NULL_VOID(layoutProperty);
257 layoutProperty->UpdateVisibility(VisibleType::GONE);
258 ref->isOutAnimationPlaying_ = false;
259 });
260
261 monthDaysRender->UpdateOpacity(0);
262 timePickerRender->UpdateOpacity(0);
263 oldColumnOpacityOutAnimation_ = AnimationUtils::StartAnimation(animationOption,
264 [monthDaysRender, timePickerRender]() {
265 CHECK_NULL_VOID_NOLOG(monthDaysRender);
266 CHECK_NULL_VOID_NOLOG(timePickerRender);
267 monthDaysRender->UpdateOpacity(1);
268 timePickerRender->UpdateOpacity(1);
269 }, animationOption.GetOnFinishEvent());
270 }
271
PlayNewColumnOpacityOutAnimation()272 void DateTimeAnimationController::PlayNewColumnOpacityOutAnimation()
273 {
274 CHECK_NULL_VOID(month_);
275 CHECK_NULL_VOID(day_);
276 auto monthRender = month_->GetRenderContext();
277 auto dayRender = day_->GetRenderContext();
278 CHECK_NULL_VOID(monthRender);
279 CHECK_NULL_VOID(dayRender);
280
281 AnimationOption animationOption;
282 animationOption.SetDelay(OPACITY_DELAY);
283 animationOption.SetDuration(OPACITY_DURATION);
284 animationOption.SetCurve(Curves::LINEAR);
285
286 monthRender->UpdateOpacity(1);
287 dayRender->UpdateOpacity(1);
288 AnimationUtils::Animate(animationOption,
289 [monthRender, dayRender]() {
290 CHECK_NULL_VOID_NOLOG(monthRender);
291 CHECK_NULL_VOID_NOLOG(dayRender);
292 monthRender->UpdateOpacity(0);
293 dayRender->UpdateOpacity(0);
294 });
295 }
296
PlayYearColumnOpacityOutAnimation()297 void DateTimeAnimationController::PlayYearColumnOpacityOutAnimation()
298 {
299 CHECK_NULL_VOID(year_);
300 auto yearRender = year_->GetRenderContext();
301 CHECK_NULL_VOID(yearRender);
302
303 AnimationOption animationOption;
304 animationOption.SetDuration(OPACITY_DURATION);
305 animationOption.SetCurve(Curves::LINEAR);
306
307 yearRender->OpacityAnimation(animationOption, 1.0f, 0.0f);
308 }
309
PlayButtonOpacityOutAnimation()310 void DateTimeAnimationController::PlayButtonOpacityOutAnimation()
311 {
312 CHECK_NULL_VOID(buttonRow_);
313 auto buttonRender = buttonRow_->GetRenderContext();
314 CHECK_NULL_VOID(buttonRender);
315
316 AnimationOption animationOption;
317 animationOption.SetDelay(OPACITY_DELAY);
318 animationOption.SetDuration(OPACITY_DURATION);
319 animationOption.SetCurve(Curves::LINEAR);
320 animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
321 auto ref = weak.Upgrade();
322 CHECK_NULL_VOID(ref);
323 auto buttonNode = ref->buttonRow_;
324 CHECK_NULL_VOID(buttonNode);
325 auto layoutProperty = buttonNode->GetLayoutProperty<LayoutProperty>();
326 CHECK_NULL_VOID(layoutProperty);
327 layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
328 auto focusHub = buttonNode->GetFocusHub();
329 CHECK_NULL_VOID(focusHub);
330 focusHub->SetShow(true);
331 });
332 buttonRender->OpacityAnimation(animationOption, 0.0f, 1.0f);
333 }
334
StopOldColumnOpacityInAnimation()335 void DateTimeAnimationController::StopOldColumnOpacityInAnimation()
336 {
337 if (oldColumnOpacityInAnimation_) {
338 AnimationUtils::StopAnimation(oldColumnOpacityInAnimation_);
339 }
340 }
341
StopOldColumnOpacityOutAnimation()342 void DateTimeAnimationController::StopOldColumnOpacityOutAnimation()
343 {
344 if (oldColumnOpacityOutAnimation_) {
345 AnimationUtils::StopAnimation(oldColumnOpacityOutAnimation_);
346 }
347 }
348
PlayInAnimation()349 void DateTimeAnimationController::PlayInAnimation()
350 {
351 isInAnimationPlaying_ = true;
352 PlayTitleInAnimation();
353 PlayMovingInAnimation();
354
355 StopOldColumnOpacityOutAnimation();
356 PlayOldColumnOpacityInAnimation();
357 PlayNewColumnOpacityInAnimation();
358 PlayYearColumnOpacityInAnimation();
359 PlayButtonOpacityInAnimation();
360 }
361
PlayOutAnimation()362 void DateTimeAnimationController::PlayOutAnimation()
363 {
364 isOutAnimationPlaying_ = true;
365 PlayTitleOutAnimation();
366 PlayMovingOutAnimation();
367
368 StopOldColumnOpacityInAnimation();
369 PlayOldColumnOpacityOutAnimation();
370 PlayNewColumnOpacityOutAnimation();
371 PlayYearColumnOpacityOutAnimation();
372 PlayButtonOpacityOutAnimation();
373 }
374
375
InitMoveRange()376 void DateTimeAnimationController::InitMoveRange()
377 {
378 yearEnd_ = 0.0;
379 monthEnd_ = 0.0;
380 dayEnd_ = 0.0;
381
382 auto yearGeometry = year_->GetGeometryNode();
383 CHECK_NULL_VOID(yearGeometry);
384 auto monthGeometry = month_->GetGeometryNode();
385 CHECK_NULL_VOID(monthGeometry);
386 yearStart_ = 0;
387 monthStart_ = 0 - yearGeometry->GetFrameSize().Width();
388 dayStart_ = monthStart_ - monthGeometry->GetFrameSize().Width();
389 }
390
391
SetDatePicker(const RefPtr<FrameNode> & value)392 void DateTimeAnimationController::SetDatePicker(const RefPtr<FrameNode>& value)
393 {
394 datePicker_ = value;
395 auto children = datePicker_->GetChildren();
396 if (children.size() != CHILD_SIZE) {
397 return;
398 }
399 auto iter = children.begin();
400 auto year = (*iter);
401 CHECK_NULL_VOID(year);
402 iter++;
403 auto month = *iter;
404 CHECK_NULL_VOID(month);
405 iter++;
406 auto day = *iter;
407 CHECK_NULL_VOID(day);
408 year_ = DynamicCast<FrameNode>(year->GetChildAtIndex(1));
409 month_ = DynamicCast<FrameNode>(month->GetChildAtIndex(1));
410 day_ = DynamicCast<FrameNode>(day->GetChildAtIndex(1));
411 }
412
Play(bool isIn)413 void DateTimeAnimationController::Play(bool isIn)
414 {
415 if (!created_) {
416 InitMoveRange();
417 created_ = true;
418 }
419
420 if (isIn) {
421 PlayInAnimation();
422 } else {
423 PlayOutAnimation();
424 }
425 }
426 } // namespace OHOS::Ace