优化省电模式退出动效 910/1 910/head
authorCaisking <3449750381@qq.com>
Sat, 7 Sep 2024 11:32:13 +0000 (19:32 +0800)
committerCaisking <3449750381@qq.com>
Sat, 7 Sep 2024 11:32:13 +0000 (19:32 +0800)
code/sdk/application/wearable/fd230app/nativeui/saveele/include/SaveBatPresenter.h
code/sdk/application/wearable/fd230app/nativeui/saveele/include/SaveBatView.h
code/sdk/application/wearable/fd230app/nativeui/saveele/include/SaveEleModel.h
code/sdk/application/wearable/fd230app/nativeui/saveele/src/SaveBatPresenter.cpp
code/sdk/application/wearable/fd230app/nativeui/saveele/src/SaveBatView.cpp

index 2c7743d..5d60a82 100644 (file)
@@ -1,3 +1,9 @@
+/***\r
+ * @Date: 2024-04-15 10:55:58\r
+ * @LastEditors: Caisking 3449750381@qq.com\r
+ * @LastEditTime: 2024-09-06 17:43:45\r
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/saveele/include/SaveBatPresenter.h\r
+ */\r
 \r
 #ifndef _SAVEBAT_PRESENTER_H\r
 #define _SAVEBAT_PRESENTER_H\r
@@ -40,14 +46,10 @@ namespace OHOS
         void Refresh_Back_View();\r
 \r
     private:\r
-        // 因为继承了OnClickListener,所以有OnClick属性,至于参数,原函数也这样直接继承;\r
-        bool OnClick(UIView &view, const ClickEvent &event) override;\r
-        bool OnDrag(UIView &view, const DragEvent &event) override;\r
-        bool OnLongPress(UIView &view, const LongPressEvent &event);\r
         bool OnPress(UIView &view, const PressEvent &event);\r
         bool OnRelease(UIView &view, const ReleaseEvent &event);\r
         bool OnKeyAct(UIView &view, const KeyEvent &event) override; // 增加按键事件\r
-\r
+        \r
         uint64_t startTime{0};\r
         int count = 3;         // 初始计数\r
         int progressValue = 0; // 初始进度值\r
index dac8f1d..668f09c 100644 (file)
 \r
 #include "SaveBatPresenter.h"\r
 #include <thread>\r
-\r
+#include "components/ui_canvas.h"\r
+#include "components/ui_scroll_view.h"\r
+#include "components/ui_canvas_ext.h"\r
+#include "components/ui_label_button.h"\r
+#include "hal_tick.h"\r
 namespace OHOS\r
 {\r
+    enum class countStage\r
+    {\r
+        STAGE_GRADUAL_CIRCLE = 0,\r
+        STAGE_COUNTING_DOWN,\r
+        STAGE_FADE_OUT,\r
+        STAGE_NONE\r
+    };\r
+    class CountdownBackAnimatorCallback : public AnimatorCallback\r
+    {\r
+    public:\r
+        explicit CountdownBackAnimatorCallback(UICanvasExt *canvas) : canvas_(canvas) {}\r
+        ~CountdownBackAnimatorCallback() override {}\r
+        void Callback(UIView *view) override;\r
+        void NotifyStart();\r
+        void CancelCountdown();\r
+        void SetInfo(UILabel *label, int counts);\r
+\r
+    private:\r
+        void CountingDown();\r
+        void UpdatePath(int16_t start, int16_t end, bool needDrawCircle);\r
+        void UpdateLable(uint32_t curTime);\r
+        void CircleFadeOut();\r
+        void GradualCircle();\r
+        UICanvasExt *canvas_ = nullptr;\r
+        UILabel *label_ = nullptr;\r
+        bool updateText_ = false;\r
+        bool firstArc_ = false;\r
+        countStage stage_ = countStage::STAGE_NONE;\r
+        int16_t endAngle_ = 0;\r
+        int16_t easeDegree_ = 0;\r
+        uint16_t idleTime_ = 0;\r
+        int16_t counts_ = 0;\r
+        uint32_t lastTime_ = 0;\r
+        uint32_t degreePerSecond_ = 0;\r
+        uint32_t surplusDegree = 0;\r
+    };\r
+\r
     class SaveBatPresenter;\r
     class SaveBatView : public View<SaveBatPresenter>\r
     {\r
@@ -58,7 +99,8 @@ namespace OHOS
         void InitShowBackView();\r
 \r
         void UpdateView();\r
-\r
+        void StartCanvas();\r
+        void StopCanvas();\r
         UILabel *GetCountlabel()\r
         {\r
             return countlabel;\r
@@ -67,6 +109,7 @@ namespace OHOS
         {\r
             return backprogress;\r
         }\r
+\r
     private:\r
         UIView::OnDragListener *draglistener{nullptr};\r
 \r
@@ -84,7 +127,13 @@ namespace OHOS
         UILabel *countlabel{nullptr};\r
         UIImageView *wathchiamge{nullptr};\r
         UICircleProgress *backprogress{nullptr};\r
-\r
+        /*test*/\r
+        CountdownBackAnimatorCallback *callBack_ = nullptr;\r
+        Animator *CountdownBackAnimator_ = nullptr;\r
+        UICanvasExt *canvas_ = nullptr;\r
+        UILabelButton *restart_ = nullptr;\r
+        UIViewGroup *container_ = nullptr;\r
+        UILabel *label_ = nullptr;\r
     };\r
 } // namespace OHOS\r
 \r
index 022731b..9ed43c9 100644 (file)
@@ -1,3 +1,9 @@
+/***
+ * @Date: 2024-08-21 16:18:26
+ * @LastEditors: Caisking 3449750381@qq.com
+ * @LastEditTime: 2024-09-06 18:19:25
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/saveele/include/SaveEleModel.h
+ */
 #ifndef SAVE_ELE_MODEL_H
 #define SAVE_ELE_MODEL_H
 
@@ -11,16 +17,16 @@ namespace OHOS
 
         // 获取充电状态
         bool GetChargeStatus();
-
-        // 设置充电状态
         void SetChargeStatus(bool chargeStatus);
 
-        // 获取视图状态
-        bool GetViewState() const { return viewState; }
-
         // 设置视图状态
+        bool GetViewState() const { return viewState; }
         void SetViewState(bool state) { viewState = state; }
 
+        // 设置退出状态
+        bool GetBackState() const { return backStatus_; }
+        void SetBackState(bool state) { backStatus_ = state; }
+
     private:
         SaveEleModel() = default; // 默认构造函数
         ~SaveEleModel() {}        // 默认析构函数
@@ -28,8 +34,9 @@ namespace OHOS
         SaveEleModel(const SaveEleModel &) = delete;            // 禁止拷贝构造
         SaveEleModel &operator=(const SaveEleModel &) = delete; // 禁止赋值操作
 
-        bool chargeStatus_{nullptr}; // 充电状态
-        bool viewState{false};       // 视图状态
+        bool chargeStatus_{false}; // 充电状态
+        bool backStatus_{false};   // 退出状态
+        bool viewState{false};     // 视图状态
     };
 }
 
index abb3848..c65dbcc 100644 (file)
@@ -63,7 +63,6 @@ namespace OHOS
 \r
     void SaveBatPresenter::OnStart()\r
     {\r
-        SaveEleModel::GetInstance()->SetChargeStatus(false);\r
         Presenter<SaveBatView>::OnStart();\r
     }\r
 \r
@@ -83,48 +82,16 @@ namespace OHOS
         Presenter<SaveBatView>::OnStop();\r
     }\r
 \r
-    bool SaveBatPresenter::OnDrag(UIView &view, const DragEvent &event)\r
-    {\r
-        UNUSED(view);\r
-        return true;\r
-    }\r
-\r
-    bool SaveBatPresenter::OnClick(UIView &view, const ClickEvent &event)\r
-    {\r
-        if (strcmp(view.GetViewId(), "button_exit") == 0)\r
-        {\r
-            /*点击*/\r
-            bool state = SaveEleModel::GetInstance()->GetViewState();\r
-            SaveEleModel::GetInstance()->SetViewState(!state);\r
-            SaveBatView::GetInstance()->UpdateView();\r
-        }\r
-        return true;\r
-    }\r
-    bool SaveBatPresenter::OnLongPress(UIView &view, const LongPressEvent &event)\r
-    {\r
-        if (strcmp(view.GetViewId(), "button_exit") == 0)\r
-        {\r
-            NativeAbility::GetInstance().ChangeSlice(VIEW_MAIN);\r
-        }\r
-        return true;\r
-    }\r
     bool SaveBatPresenter::OnPress(UIView &view, const PressEvent &event)\r
     {\r
         if (strcmp(view.GetViewId(), "button_exit") == 0)\r
         {\r
-            /*\r
-                uint64_t current_time = osKernelGetTick2ms();\r
-                SaveBatView::GetInstance()->Refresh_Back_View();\r
-                if (IS_TIME_EXCEED(startTime, current_time))\r
-                {\r
-                NativeAbility::GetInstance().ChangeSlice(VIEW_MAIN);\r
-            }\r
-            */\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "进行按下");\r
             if (SaveEleModel::GetInstance()->GetViewState() == false)\r
             {\r
                 SaveEleModel::GetInstance()->SetViewState(true);\r
                 SaveBatView::GetInstance()->UpdateView();\r
-                ResetTickTimer();\r
+                SaveBatView::GetInstance()->StartCanvas();\r
             }\r
         }\r
         return true;\r
@@ -133,37 +100,36 @@ namespace OHOS
     {\r
         if (strcmp(view.GetViewId(), "button_exit") == 0)\r
         {\r
-            /*释放*/\r
-            SaveEleModel::GetInstance()->SetViewState(false);\r
-            SaveBatView::GetInstance()->UpdateView();\r
-            /*重置*/\r
-            progressValue = 0;\r
-            count = 3;\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "进行松开");\r
+            if (SaveEleModel::GetInstance()->GetViewState() == true)\r
+            {\r
+                SaveBatView::GetInstance()->StopCanvas();\r
+                SaveEleModel::GetInstance()->SetViewState(false);\r
+                SaveBatView::GetInstance()->UpdateView();\r
+            }\r
         }\r
         return true;\r
     }\r
     void SaveBatPresenter::ExitView(void)\r
     {\r
-        bool isCharging = SaveEleModel::GetInstance()->GetChargeStatus(); // 获取充电状态\r
-        // 如果省电模式中发生充电变化->进行退出\r
-        if (isCharging)\r
-        {\r
-            NativeAbility::GetInstance().ChangeSlice(VIEW_MAIN);\r
-        }\r
+        NativeAbility::GetInstance().ChangeSlice(VIEW_MAIN);\r
     }\r
 \r
     void SaveBatPresenter::OnTickEvent()\r
     {\r
-        uint64_t current_time = osKernelGetTick2ms();\r
         /*省电表盘界面*/\r
         if (SaveEleModel::GetInstance()->GetViewState() == false)\r
         {\r
             SaveBatView::GetInstance()->Refresh_Dial_View();\r
-            ExitView();\r
         }\r
-        else if (SaveEleModel::GetInstance()->GetViewState() == true)\r
+        /*退出判断*/\r
+        bool chargeStatus = SaveEleModel::GetInstance()->GetChargeStatus();\r
+        bool backState = SaveEleModel::GetInstance()->GetBackState();\r
+        if (chargeStatus || backState)\r
         {\r
-            Refresh_Back_View();\r
+            WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "退出省电模式 Charge_Status: %d, Back_State: %d", chargeStatus, backState);\r
+            SaveEleModel::GetInstance()->SetBackState(false);\r
+            ExitView();\r
         }\r
     }\r
     void SaveBatPresenter::ResetTickTimer(void)\r
index 8649db8..ab235ba 100644 (file)
@@ -15,6 +15,7 @@
 #include "custom_utils.h"\r
 #include "UiConfig.h"\r
 #include "wearable_log.h"\r
+#define ANIMATION_TEST 0\r
 extern "C"\r
 {\r
     void uapi_exit_power_saving_mode(void);\r
@@ -30,12 +31,294 @@ static constexpr const char *SAVE_WATHCH = "/user/res/Save_Ele/wathch.bin";
 \r
 namespace OHOS\r
 {\r
+    /*动画类实现*/\r
+    const static int16_t CENTER_X = 233;\r
+    const static int16_t CENTER_Y = 233;\r
+    const static int16_t LABEL_X = 140;\r
+    const static int16_t LABEL_Y = 170;\r
+    const static int16_t RADIUS = 90; // 半径 90\r
+    const static int16_t STROKE_WIDTH = 20;\r
+    const static int16_t CIRCLE_BASE_WIDTH = 4;\r
+    const static uint32_t LIGHT_GREEN = 0xff007700;\r
+    static const uint16_t LABEL_FONT_SIZE = 80;\r
+    static const uint16_t ANIMATE_TIME = 500;\r
+    static const uint16_t SECOND_TO_MINISECOND = 1000;\r
+    static const uint16_t CIRCLE_FADE_OUT = 200;\r
+    static const uint16_t DEGREES_PER_CIRCLE = 360;\r
+    void CountdownBackAnimatorCallback::Callback(UIView *view)\r
+    {\r
+        // 根据当前阶段调用相应的功能,控制动画状态\r
+        switch (stage_)\r
+        {\r
+        case countStage::STAGE_GRADUAL_CIRCLE:\r
+        {\r
+            // 处理渐变圆圈绘制\r
+            GradualCircle();\r
+            break;\r
+        }\r
+        case countStage::STAGE_COUNTING_DOWN:\r
+        {\r
+            // 处理倒计时逻辑\r
+            CountingDown();\r
+            break;\r
+        }\r
+        case countStage::STAGE_FADE_OUT:\r
+        {\r
+            // 处理圆圈淡出效果\r
+            CircleFadeOut();\r
+            break;\r
+        }\r
+        default:\r
+            break;\r
+        }\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::CircleFadeOut()\r
+    {\r
+        // 计算当前时间与上次更新时间的差值\r
+        uint32_t diffTime = HALTick::GetInstance().GetTime() - lastTime_;\r
+\r
+        // 如果尚未达到空闲时间,则什么也不做\r
+        if (diffTime < idleTime_)\r
+        {\r
+            return;\r
+        }\r
+\r
+        // 清空画布以准备绘制\r
+        canvas_->Clear();\r
+\r
+        // 计算当前的圆圈宽度\r
+        uint32_t curTime = diffTime - idleTime_;\r
+        uint16_t width;\r
+\r
+        // 判断是否已经达到淡出持续时间\r
+        if (curTime >= CIRCLE_FADE_OUT)\r
+        {\r
+            curTime = CIRCLE_FADE_OUT;       // 限制为最大淡出时间\r
+            stage_ = countStage::STAGE_NONE; // 设置为无状态\r
+        }\r
+\r
+        // 使用缓动方程计算当前宽度\r
+        width = EasingEquation::QuadEaseInOut(STROKE_WIDTH, CIRCLE_BASE_WIDTH, curTime, CIRCLE_FADE_OUT);\r
+\r
+        // 绘制中心圆圈\r
+        Point center = {CENTER_X, CENTER_Y};\r
+        ColorType lightGreen;\r
+        lightGreen.full = LIGHT_GREEN;\r
+        PaintExt paint;\r
+        paint.SetStyle(Paint::PaintStyle::STROKE_STYLE);\r
+        paint.SetCapType(CAP_ROUND);\r
+        paint.SetAntialiased(true);\r
+        paint.SetStrokeColor(lightGreen);\r
+        paint.SetStrokeWidth(width);\r
+        canvas_->DrawCircle(center, RADIUS, paint);\r
+\r
+        // 更新标签的字体大小和透明度\r
+        uint16_t fontSize = LABEL_FONT_SIZE * width / STROKE_WIDTH; // 根据笔画宽度调整字体大小\r
+        uint16_t opa = OPA_OPAQUE * width / STROKE_WIDTH;           // 根据笔画宽度调整透明度\r
+        if (stage_ == countStage::STAGE_NONE)\r
+        {\r
+            opa = OPA_TRANSPARENT; // 如果处于无状态,设置为完全透明\r
+        }\r
+\r
+        label_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, fontSize);\r
+        label_->SetStyle(STYLE_TEXT_OPA, opa); // 更新标签样式\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::UpdateLable(uint32_t curTime)\r
+    {\r
+        char buf[2] = {0}; // 字符缓冲区,用于格式化标签文本\r
+        uint16_t fontSize; // 字体大小\r
+        uint16_t opa;      // 透明度\r
+\r
+        // 前半段动画,字体逐渐变小\r
+        if (curTime < ANIMATE_TIME / 2)\r
+        {\r
+            fontSize = LABEL_FONT_SIZE - LABEL_FONT_SIZE * curTime * 2 / ANIMATE_TIME; // 计算当前字体大小\r
+            opa = OPA_OPAQUE * fontSize / LABEL_FONT_SIZE;                             // 计算当前透明度\r
+            if (firstArc_)\r
+            {\r
+                fontSize = fontSize / 2; // 如果是第一弧,字体设置为一半大小\r
+            }\r
+        }\r
+        else\r
+        {\r
+            // 后半段动画,字体逐渐增大\r
+            fontSize = LABEL_FONT_SIZE * curTime * 2 / ANIMATE_TIME - LABEL_FONT_SIZE;\r
+            opa = OPA_OPAQUE * fontSize / LABEL_FONT_SIZE;\r
+\r
+            // 更新标签文本\r
+            if (updateText_)\r
+            {\r
+                if (sprintf_s(buf, sizeof(buf), "%u", (endAngle_ + easeDegree_) / degreePerSecond_) < 0)\r
+                {\r
+                    return; // 如果 sprintf_s 出错,返回\r
+                }\r
+                label_->SetText(buf); // 设置标签文本为当前倒计时数字\r
+                updateText_ = false;  // 更新文本之后将标志置为false\r
+            }\r
+        }\r
+\r
+        // 更新标签的字体和样式\r
+        label_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, fontSize);\r
+        label_->SetStyle(STYLE_TEXT_OPA, opa);\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::UpdatePath(int16_t start, int16_t end, bool needDrawCircle)\r
+    {\r
+        // 计算绘制的圆心和颜色\r
+        Point center = {CENTER_X, CENTER_Y};\r
+        ColorType lightGreen;\r
+        lightGreen.full = LIGHT_GREEN;\r
+        PaintExt paint;\r
+        paint.SetStyle(Paint::PaintStyle::STROKE_STYLE);\r
+        paint.SetStrokeWidth(STROKE_WIDTH);\r
+        paint.SetCapType(CAP_ROUND);\r
+        paint.SetAntialiased(true);\r
+        paint.SetStrokeColor(lightGreen);\r
+\r
+        // 清空画布\r
+        canvas_->Clear();\r
+        // 如果需要绘制基础圆圈,则绘制\r
+        if (needDrawCircle)\r
+        {\r
+            canvas_->DrawCircle(center, RADIUS, paint);\r
+        }\r
+\r
+        // 如果起始角度与结束角度不相同,则绘制弧线\r
+        if (start != end)\r
+        {\r
+            paint.SetStrokeColor(Color::Green()); // 设置弧线颜色为绿色\r
+            // 如果起始角和结束角相差完整的一圈,则绘制完整的圆圈\r
+            if (end - start == DEGREES_PER_CIRCLE)\r
+            {\r
+                canvas_->DrawCircle(center, RADIUS, paint);\r
+            }\r
+            else\r
+            {\r
+                // 绘制从起始角到结束角\r
+                // 绘制从起始角到结束角的弧线\r
+                canvas_->DrawArc(center, RADIUS, start, end, paint);\r
+            }\r
+        }\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::CountingDown()\r
+    {\r
+        // 计算当前时间与上次更新时间的差值\r
+        uint32_t diffTime = HALTick::GetInstance().GetTime() - lastTime_;\r
+\r
+        // 如果时间差达到1秒,则更新倒计时\r
+        if (diffTime >= SECOND_TO_MINISECOND)\r
+        {\r
+            lastTime_ = HALTick::GetInstance().GetTime(); // 更新最后时间\r
+            // 判断是否是第一次绘制弧线\r
+            if (endAngle_ == DEGREES_PER_CIRCLE)\r
+            {\r
+                firstArc_ = true; // 如果是第一次,设置标志\r
+            }\r
+            else\r
+            {\r
+                firstArc_ = false; // 否则,设置为非第一次\r
+            }\r
+            // 更新路径和标签\r
+            UpdatePath(0, endAngle_, true);\r
+            UpdateLable(0);\r
+\r
+            // 如果倒计时结束,切换到淡出阶段\r
+            if (endAngle_ == 0)\r
+            {\r
+                stage_ = countStage::STAGE_FADE_OUT;\r
+                idleTime_ = SECOND_TO_MINISECOND - CIRCLE_FADE_OUT; // 设置空闲时间\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "倒计时结束");\r
+                OHOS::SaveEleModel::GetInstance()->SetBackState(true); // 进行界面弹出\r
+                return;\r
+            }\r
+\r
+            // 更新结束角度和缓动角度\r
+            easeDegree_ = degreePerSecond_;\r
+            endAngle_ -= degreePerSecond_; // 减少结束角度\r
+            // 如果结束角度小于等于剩余角度,则重置结束角度\r
+            if (endAngle_ <= surplusDegree)\r
+            {\r
+                endAngle_ = 0;\r
+                easeDegree_ += surplusDegree; // 增加缓动角度\r
+            }\r
+            updateText_ = true; // 标记需要更新文本\r
+        }\r
+        else if (diffTime >= idleTime_)\r
+        {\r
+            // 如果时间差超过空闲时间,更新路径和标签\r
+            uint32_t curTime = diffTime - idleTime_;\r
+            int16_t arcCurr = EasingEquation::QuadEaseInOut(0, easeDegree_, curTime, ANIMATE_TIME);\r
+            UpdatePath(0, endAngle_ + easeDegree_ - arcCurr, true);\r
+            UpdateLable(curTime);\r
+        }\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::GradualCircle()\r
+    {\r
+        // 计算当前时间与上次更新时间的差值\r
+        uint32_t diffTime = HALTick::GetInstance().GetTime() - lastTime_;\r
+\r
+        // 如果时间差达到1秒,则切换到倒计时阶段\r
+        if (diffTime >= SECOND_TO_MINISECOND)\r
+        {\r
+            stage_ = countStage::STAGE_COUNTING_DOWN;        // 切换阶段\r
+            idleTime_ = SECOND_TO_MINISECOND - ANIMATE_TIME; // 设置空闲时间\r
+        }\r
+        else if (diffTime >= idleTime_)\r
+        {\r
+            // 如果时间差超过空闲时间,绘制渐变圆圈\r
+            uint32_t curTime = diffTime - idleTime_;\r
+            int16_t arcCurr = EasingEquation::QuadEaseInOut(0, DEGREES_PER_CIRCLE,\r
+                                                            curTime, SECOND_TO_MINISECOND - idleTime_);\r
+            UpdatePath(180, arcCurr + 180, false); // 从180度开始绘制\r
+        }\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::SetInfo(UILabel *label, int counts)\r
+    {\r
+        // 设置标签和计数值\r
+        counts_ = counts; // 记录倒计时的总次数\r
+        label_ = label;   // 记录UILabel对象\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::NotifyStart()\r
+    {\r
+        // 初始化倒计时动画的状态\r
+        stage_ = countStage::STAGE_GRADUAL_CIRCLE;                       // 设置为渐变圆圈阶段\r
+        endAngle_ = DEGREES_PER_CIRCLE;                                  // 设置结束角度为完整一圈\r
+        idleTime_ = 200;                                                 // 设置初始空闲时间\r
+        degreePerSecond_ = DEGREES_PER_CIRCLE / counts_;                 // 计算每秒减少的角度\r
+        surplusDegree = DEGREES_PER_CIRCLE - degreePerSecond_ * counts_; // 计算剩余角度\r
+        lastTime_ = HALTick::GetInstance().GetTime();                    // 记录当前时间\r
+\r
+        // 初始化标签文本和样式\r
+        label_->SetText(" ");\r
+        label_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, LABEL_FONT_SIZE / 2); // 设置字体为一半大小\r
+        label_->SetStyle(STYLE_TEXT_OPA, OPA_OPAQUE);                       // 设置标签为不透明\r
+    }\r
+\r
+    void CountdownBackAnimatorCallback::CancelCountdown()\r
+    {\r
+        // 设置阶段为淡出\r
+        stage_ = countStage::STAGE_FADE_OUT;\r
+\r
+        // 重置时间以立即开始淡出\r
+        lastTime_ = HALTick::GetInstance().GetTime(); // 记录当前时间\r
+        idleTime_ = 0;                                // 设置空闲时间为零,以跳过任何等待时间\r
+\r
+        endAngle_ = 0; // 设置结束角度为0,表示取消倒计时\r
+    }\r
+\r
     static SaveBatView *g_pSaveBatView{nullptr};\r
 \r
     SaveBatView::SaveBatView()\r
     {\r
         /*开启省电模式*/\r
         uapi_enter_power_saving_mode();\r
+\r
         g_pSaveBatView = this;\r
     }\r
 \r
@@ -199,8 +482,6 @@ namespace OHOS
         button_exit->SetImageSrc(SAVE_BUTTON, SAVE_BUTTON);\r
         button_exit->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff000000, UIButton::PRESSED);\r
 \r
-        // button_exit->SetOnLongPressListener(presenter_);\r
-        // button_exit->SetOnClickListener(presenter_);\r
         button_exit->SetOnTouchListener(presenter_);\r
         container_->Add(button_exit);\r
     }\r
@@ -235,7 +516,7 @@ namespace OHOS
         curren_label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 40);\r
         container_->Add(curren_label);\r
         curren_label->SetVisible(false);\r
-\r
+#if ANIMATION_TEST\r
         // 圆形进度条\r
         backprogress = new UICircleProgress();\r
         if (backprogress == nullptr)\r
@@ -292,6 +573,51 @@ namespace OHOS
         countlabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 40);\r
         container_->Add(countlabel);\r
         countlabel->SetVisible(false);\r
+#else\r
+        if (canvas_ == nullptr)\r
+        {\r
+            canvas_ = new UICanvasExt();\r
+        }\r
+        canvas_->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());\r
+        canvas_->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);\r
+        container_->Add(canvas_);\r
+        canvas_->SetVisible(false);\r
+\r
+        if (label_ == nullptr)\r
+        {\r
+            label_ = new UILabel();\r
+        }\r
+        label_->SetPosition(LABEL_X, LABEL_Y, 180, 120);\r
+        label_->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);\r
+        container_->Add(label_);\r
+        label_->SetVisible(false);\r
+\r
+        PaintExt paint;\r
+        ColorType lightGreen;\r
+        lightGreen.full = LIGHT_GREEN;\r
+        paint.SetStyle(Paint::PaintStyle::STROKE_STYLE);\r
+        paint.SetStrokeWidth(CIRCLE_BASE_WIDTH);\r
+        paint.SetAntialiased(true);\r
+        paint.SetStrokeColor(lightGreen);\r
+        canvas_->DrawCircle({CENTER_X, CENTER_Y}, RADIUS, paint);\r
+\r
+        callBack_ = new CountdownBackAnimatorCallback(canvas_);\r
+        if (callBack_ == nullptr)\r
+        {\r
+            GRAPHIC_LOGE("CallBack new fail");\r
+            return;\r
+        }\r
+        CountdownBackAnimator_ = new Animator(callBack_, canvas_, 0, true);\r
+        if (CountdownBackAnimator_ == nullptr)\r
+        {\r
+            delete callBack_;\r
+            callBack_ = nullptr;\r
+            GRAPHIC_LOGE("Animator new fail");\r
+            return;\r
+        }\r
+        CountdownBackAnimator_->Start();\r
+        callBack_->SetInfo(label_, 3); // 3: countdown numbers\r
+#endif\r
     }\r
 \r
     // 更新当前界面状态\r
@@ -299,86 +625,118 @@ namespace OHOS
     {\r
         bool state = SaveEleModel::GetInstance()->GetViewState();\r
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateView state %d", state);\r
-#if 0\r
+\r
         // 检查每个组件是否为空,并记录具体信息\r
         if (timelabel == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "timelabel is null");\r
+            return;\r
         }\r
         if (datelabel == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "datelabel is null");\r
+            return;\r
         }\r
         if (batterylabel == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "batterylabel is null");\r
+            return;\r
         }\r
         if (batteryprogress == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "batteryprogress is null");\r
+            return;\r
         }\r
         if (batteryiamge == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "batteryiamge is null");\r
+            return;\r
         }\r
         if (curren_label == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "curren_label is null");\r
+            return;\r
         }\r
+#if ANIMATION_TEST\r
         if (countlabel == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "countlabel is null");\r
+            return;\r
         }\r
         if (wathchiamge == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "wathchiamge is null");\r
+            return;\r
         }\r
         if (backprogress == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "backprogress is null");\r
+            return;\r
         }\r
+#endif\r
         if (button_exit == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "button_exit is null");\r
-        }\r
-#endif\r
-        // 如果有任何组件为空,返回\r
-        if (timelabel == nullptr || datelabel == nullptr || batterylabel == nullptr || batteryprogress == nullptr ||\r
-            batteryiamge == nullptr || curren_label == nullptr ||\r
-            countlabel == nullptr || wathchiamge == nullptr || backprogress == nullptr || button_exit == nullptr)\r
-        {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "One or more view components are null.");\r
             return;\r
         }\r
 \r
-        /*原界面*/\r
-        timelabel->SetVisible(!state);\r
-        datelabel->SetVisible(!state);\r
-        batterylabel->SetVisible(!state);\r
-        batteryprogress->SetVisible(!state);\r
-        batteryiamge->SetVisible(!state);\r
-\r
-        /*重置计数器*/\r
-        int count = 3;         // 初始计数\r
-        int progressValue = 0; // 初始进度值\r
+        // 显示/隐藏原界面组件\r
+        bool showPrimaryView = !state;\r
+        timelabel->SetVisible(showPrimaryView);\r
+        datelabel->SetVisible(showPrimaryView);\r
+        batterylabel->SetVisible(showPrimaryView);\r
+        batteryprogress->SetVisible(showPrimaryView);\r
+        batteryiamge->SetVisible(showPrimaryView);\r
+\r
+#if ANIMATION_TEST\r
+        // 初始化计数器\r
+        int count = 3;\r
+        int progressValue = 0;\r
         countlabel->SetText(std::to_string(count).c_str());\r
         backprogress->SetValue(progressValue);\r
 \r
-        /*退出界面*/\r
+        /* 退出界面 */\r
         curren_label->SetVisible(state);\r
         countlabel->SetVisible(state);\r
         wathchiamge->SetVisible(state);\r
         backprogress->SetVisible(state);\r
 \r
-        if (state)\r
-        {\r
-            button_exit->SetImageSrc(BACK_BUTTON, BACK_BUTTON);\r
-        }\r
-        else\r
-        {\r
-            button_exit->SetImageSrc(SAVE_BUTTON, SAVE_BUTTON);\r
-        }\r
+#else\r
+        /* 退出界面 */\r
+        curren_label->SetVisible(state);\r
+\r
+        // 显示当前时间\r
+        time_t seconds;\r
+        time(&seconds);\r
+        struct tm pTM;\r
+        localtime_r(&seconds, &pTM);\r
+\r
+        int hour = pTM.tm_hour;\r
+        int minute = pTM.tm_min;\r
+        std::string stringtime =\r
+            (hour < 10 ? "0" : "") + std::to_string(hour) + ":" +\r
+            (minute < 10 ? "0" : "") + std::to_string(minute);\r
+        curren_label->SetText(stringtime.c_str());\r
+        label_->SetVisible(state);\r
+        canvas_->SetVisible(state);\r
+\r
+#endif\r
+\r
+        // 设置退出按钮图像\r
+        const char *buttonImage = state ? BACK_BUTTON : SAVE_BUTTON;\r
+        button_exit->SetImageSrc(buttonImage, buttonImage);\r
+    }\r
+\r
+    /*动画的控制*/\r
+    void SaveBatView::StartCanvas()\r
+    {\r
+        callBack_->NotifyStart();\r
+    }\r
+    void SaveBatView::StopCanvas()\r
+    {\r
+        callBack_->CancelCountdown();\r
     }\r
+\r
     void SaveBatView::OnStart()\r
     {\r
         container_ = new UIViewGroup();\r