实现计时器计时功能,还差倒计时到期响铃功能
authorluozheng <1732036298@qq.com>
Mon, 8 Apr 2024 12:47:19 +0000 (20:47 +0800)
committerluozheng <1732036298@qq.com>
Mon, 8 Apr 2024 12:47:19 +0000 (20:47 +0800)
code/sdk/application/wearable/fd230app/nativeui/countdown/include/CountDownModel.h
code/sdk/application/wearable/fd230app/nativeui/countdown/include/MainCountDownPresenter.h
code/sdk/application/wearable/fd230app/nativeui/countdown/include/StartCountDownView.h
code/sdk/application/wearable/fd230app/nativeui/countdown/src/CountDownModel.cpp
code/sdk/application/wearable/fd230app/nativeui/countdown/src/MainCountDownPresenter.cpp
code/sdk/application/wearable/fd230app/nativeui/countdown/src/StartCountDownView.cpp
code/sdk/application/wearable/fd230app/nativeui/stopwatch/src/StopWatchModel.cpp

index 47b8e6e..147a40e 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: luozheng 1732036298@qq.com\r
  * @Date: 2024-04-07 18:15:53\r
  * @LastEditors: luozheng 1732036298@qq.com\r
- * @LastEditTime: 2024-04-07 21:14:31\r
+ * @LastEditTime: 2024-04-08 19:42:10\r
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/countdown/include/CountDownModel.h\r
  */\r
 #ifndef COUNTDOWN_MODEL_H\r
@@ -14,18 +14,26 @@ namespace OHOS
     class CountDownModel\r
     {\r
     public:\r
-        \r
         static CountDownModel *GetInstance(); // shared_ptr:当没有引用指向这个实例时会自动释放内存\r
-        \r
+\r
         void SetCountDownTime(const std::string &countdowntime); // 设置倒计时时间\r
         std::string GetCountDownTime(void);                      // 获取倒计时时间\r
         void SetRingTime(const std::string &ringtime);           // 设置响铃时间\r
         std::string GetRingTime(void);                           // 获取响铃时间\r
+        void ParseCountDownTime(const char *countdowntime);\r
+        std::string ParseRingTime(const std::string &ringtime);\r
+        const char *DisplayCountDownDuration();\r
+        void CountDown_StartTimer(uint32_t interval);\r
+        void CountDown_StopTimer(void);\r
+        void CountDown_PauseTimer(void);\r
+        void CountDown_ResumeTimer(uint32_t interval);\r
+\r
+        static int g_CountDownTimes;\r
 \r
     private:\r
         CountDownModel() {}\r
         ~CountDownModel() {}\r
-\r
+        std::string countdownDuration{nullptr};\r
         std::string RingTime{"00:00:00"};  // 响铃时间\r
         std::string CountTime{"00:00:00"}; // 倒计时时间\r
     };\r
index c3b8ead..fc0b9e2 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: luozheng 1732036298@qq.com\r
  * @Date: 2024-04-07 18:15:53\r
  * @LastEditors: luozheng 1732036298@qq.com\r
- * @LastEditTime: 2024-04-08 14:39:58\r
+ * @LastEditTime: 2024-04-08 20:17:52\r
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/countdown/include/MainCountDownPresenter.h\r
  */\r
 #ifndef MAIN_COUNTDOWN_PRESENTER_H\r
@@ -24,6 +24,7 @@ namespace OHOS
         COUNTDOWN_MAX,\r
     } CountDownViewId;\r
 \r
+    static constexpr const int COUNTDOWN_TIMER_DURATION = 1000; // 计时器的定时器周期\r
     class MainCountDownView;\r
     class MainCountDownPresenter : public Presenter<MainCountDownView>,\r
                                    public UIView::OnClickListener,\r
index b8ac24e..ddc0ad3 100644 (file)
@@ -31,7 +31,9 @@ namespace OHOS
         UIScrollView *StartCountDownViewInit(void);\r
         void ClearAll(void);\r
         UILabelExt *GetShowCountDownTimelabel(void); // 获取显示倒计时时间标签\r
-        UILabelExt *GetShowTheRingTimelabel(void);    // 获取显示响铃时间标签\r
+        UILabelExt *GetShowTheRingTimelabel(void);   // 获取显示响铃时间标签\r
+        UIToggleButton *GetPlayOrPauseToggleButton(void);\r
+\r
     private:\r
         UIScrollView *scrollView = nullptr;\r
         UILabelExt *Title = nullptr;\r
index 61ad9b7..1480926 100644 (file)
@@ -2,44 +2,27 @@
  * @Author: luozheng 1732036298@qq.com\r
  * @Date: 2024-04-07 18:15:53\r
  * @LastEditors: luozheng 1732036298@qq.com\r
- * @LastEditTime: 2024-04-07 21:13:35\r
+ * @LastEditTime: 2024-04-08 20:43:16\r
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/countdown/src/CountDownModel.cpp\r
  */\r
 #include "countdown/include/CountDownModel.h"\r
-#include <sstream>\r
-#include <sstream>\r
-#include <iomanip>\r
+#include <cmsis_os2.h>\r
+#include <ohos_types.h>\r
+#include <service/graphic_service.h>\r
+#include "wearable_log.h"\r
+#include "countdown/include/MainCountDownView.h"\r
+#include <cmsis_os.h>\r
 namespace OHOS\r
 {\r
     /* -------------------------------------------------------------------------- */\r
-    struct Time\r
-    {\r
-        int hour;\r
-        int minute;\r
-        int second;\r
-    };\r
-    // 解析时间字符串并返回 Time 结构体\r
-    static Time ParseTimeString(const std::string &timeString)\r
-    {\r
-        Time time;\r
-\r
-        std::stringstream ss(timeString);\r
-        char delimiter;\r
+    // 声明定时器变量\r
+    static osTimerId_t g_timer = NULL;\r
+    int CountDownModel::g_CountDownTimes = {0};\r
+    static constexpr int32 NUM_TEN = 10; // 主要用于格式化输出,当小时、分钟或秒小于10时,在其前面添加一个’0’以保持常规时间格式,例如“09:05:03”。\r
+    static constexpr int16 NUM_TIME_MIN = 60;\r
+    static constexpr int16 NUM_TIME_HOUR = 3600;\r
+    static constexpr int32 NUM_TIME_DAY = 86400;\r
 \r
-        ss >> time.hour >> delimiter >> time.minute >> delimiter >> time.second;\r
-\r
-        return time;\r
-    }\r
-    // 格式化时间:确保它是 “hh:mm:ss” 格式\r
-    std::string FormatTime(int hours, int minutes, int seconds)\r
-    {\r
-        std::ostringstream oss;\r
-        oss << std::setw(2) << std::setfill('0') << hours << ":"\r
-            << std::setw(2) << std::setfill('0') << minutes << ":"\r
-            << std::setw(2) << std::setfill('0') << seconds;\r
-\r
-        return oss.str();\r
-    }\r
     /* -------------------------------------------------------------------------- */\r
     // 定义了 GetInstance() 方法来获取 CountDownModel 的实例,确保只有一个全局实例存在。\r
     CountDownModel *CountDownModel::GetInstance()\r
@@ -48,10 +31,57 @@ namespace OHOS
         return &instance;\r
     }\r
 \r
+    // 函数用于解析"HH:MM:SS"格式的时间字符串,并更新g_CountDownTimes\r
+    void CountDownModel::ParseCountDownTime(const char *countdowntime)\r
+    {\r
+        int hours, minutes, seconds;\r
+\r
+        // 使用sscanf从字符串中读取格式化数据\r
+        // "%2d:%2d:%2d"用于检查两个数字,后面跟一个冒号,这样的模式重复两次,从而捕获三个整数\r
+        if (sscanf(countdowntime, "%2d:%2d:%2d", &hours, &minutes, &seconds) == 3)\r
+        {\r
+            // 解析成功,现在转换为总秒数\r
+            g_CountDownTimes = hours * NUM_TIME_HOUR + minutes * NUM_TIME_MIN + seconds;\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "g_CountDownTimes = %d", g_CountDownTimes);\r
+        }\r
+        else\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CountDownModel::ParseCountDownTime Parsing failure");\r
+        }\r
+    }\r
+\r
+    std::string CountDownModel::ParseRingTime(const std::string &timeStr)\r
+    {\r
+        int hours, minutes, seconds;\r
+        std::string formattedTime;\r
+        // 使用 sscanf 从字符串中读取时间数据\r
+        if (sscanf(timeStr.c_str(), "%2d:%2d:%2d", &hours, &minutes, &seconds) == 3)\r
+        {\r
+            // 如果小时部分为0,则格式化去掉小时部分\r
+            if (hours == 0)\r
+            {\r
+                formattedTime = (minutes < NUM_TEN ? "0" : "") + std::to_string(minutes) + ":" + (seconds < NUM_TEN ? "0" : "") + std::to_string(seconds);\r
+            }\r
+            else\r
+            {\r
+                // 如果小时部分不为0,保持原有格式\r
+                formattedTime = timeStr;\r
+            }\r
+        }\r
+        else\r
+        {\r
+            // 解析失败逻辑处理:可以选择记录错误、返回原字符串或其他合适的处理方式\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TrimTimeFormat Parsing failure: Invalid format");\r
+            formattedTime = timeStr; // 例子中选择返回原字符串\r
+        }\r
+        return formattedTime;\r
+    }\r
+\r
     // 设置倒计时时间\r
     void CountDownModel::SetCountDownTime(const std::string &countdowntime)\r
     {\r
         CountTime = countdowntime;\r
+        ParseCountDownTime(CountTime.c_str());\r
     }\r
 \r
     // 获取倒计时时间\r
@@ -63,14 +93,7 @@ namespace OHOS
     // 设置响铃时间\r
     void CountDownModel::SetRingTime(const std::string &ringtime)\r
     {\r
-        Time time = ParseTimeString(ringtime);\r
-        if (time.hour == 0) // 如果倒计时时间小于一小时就只显示分钟和秒\r
-        {\r
-            std::string rt = ringtime.substr(3, 5); //"00:05:00":从第3个位置开始截图5个字符 ,substr不会修改原来的字符串\r
-            RingTime = rt;\r
-            return;\r
-        }\r
-        RingTime = ringtime;\r
+        RingTime = ParseRingTime(ringtime);\r
     }\r
 \r
     // 获取响铃时间\r
@@ -79,4 +102,175 @@ namespace OHOS
         return RingTime;\r
     }\r
 \r
+    /* ----------------------------------- 定时器 ---------------------------------- */\r
+\r
+    /*\r
+     * @brief 显示计时器(时、分、秒)\r
+     */\r
+    const char *CountDownModel::DisplayCountDownDuration()\r
+    {\r
+        countdownDuration.clear(); // 更正为clear(),更加表明意图,与erase()等价\r
+        std::string hours;\r
+        std::string minute;\r
+        std::string seconds;\r
+\r
+        if (g_CountDownTimes >= NUM_TIME_DAY)\r
+        {\r
+            g_CountDownTimes = 0;\r
+        }\r
+\r
+        int hour = g_CountDownTimes / NUM_TIME_HOUR;\r
+        int min = (g_CountDownTimes % NUM_TIME_HOUR) / NUM_TIME_MIN;\r
+        int sec = (g_CountDownTimes % NUM_TIME_HOUR) % NUM_TIME_MIN;\r
+\r
+        hours = (hour < NUM_TEN) ? "0" + std::to_string(hour) : std::to_string(hour);\r
+        minute = (min < NUM_TEN) ? "0" + std::to_string(min) : std::to_string(min);\r
+        seconds = (sec < NUM_TEN) ? "0" + std::to_string(sec) : std::to_string(sec);\r
+        countdownDuration = hours + ":" + minute + ":" + seconds;\r
+\r
+        return countdownDuration.c_str(); // 返回 std::string 的 c_str(),但需要注意生命周期\r
+    }\r
+    /*\r
+     * @brief 在这里添加定时器到期后的处理逻辑\r
+     */\r
+    static void CountDown_TimerCallbackProc(int data)\r
+    {\r
+        CountDownModel::g_CountDownTimes--; // 每次回调减少1秒\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "g_CountDownTimes:%d\n", CountDownModel::g_CountDownTimes);\r
+\r
+        if (MainCountDownView::GetInstance() == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[CountDown_TimerCallbackProc] GetInstance is NULL");\r
+            return;\r
+        }\r
+\r
+        if (MainCountDownView::GetInstance()->GetStartCountDownView()->GetShowCountDownTimelabel() == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[CountDown_TimerCallbackProc] GetShowCountDownTimelabel is NULL");\r
+            return;\r
+        }\r
+\r
+        if (CountDownModel::GetInstance()->DisplayCountDownDuration() == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[CountDown_TimerCallbackProc] DisplayCountDownDuration is NULL");\r
+            return;\r
+        }\r
+\r
+        // 检查倒计时是否结束\r
+        if (CountDownModel::g_CountDownTimes <= 0)\r
+        {\r
+            CountDownModel::GetInstance()->CountDown_StopTimer(); // 停止定时器\r
+            MainCountDownView::GetInstance()->GetStartCountDownView()->GetShowCountDownTimelabel()->SetText("倒计时结束");\r
+            // 进行倒计时结束时的额外操作,比如播放声音、显示通知等\r
+        }\r
+        else\r
+        {\r
+            // 更新显示\r
+            MainCountDownView::GetInstance()->GetStartCountDownView()->GetShowCountDownTimelabel()->SetText(CountDownModel::GetInstance()->DisplayCountDownDuration());\r
+        }\r
+    }\r
+\r
+    /*\r
+     * @brief 计时器回调函数\r
+     */\r
+    static void CountDown_TimerCallback(int data)\r
+    {\r
+        GraphicService::GetInstance()->PostGraphicEvent(std::bind(CountDown_TimerCallbackProc, data));\r
+    }\r
+\r
+    /*\r
+     *  @brief 开启定时器函数\r
+     *  @param interval 时间间隔,单位ms\r
+     */\r
+    void CountDownModel::CountDown_StartTimer(uint32_t interval)\r
+    {\r
+        /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */\r
+        if (g_timer != NULL)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CountDownModel::CountDown_StartTimer Timer already exists!!");\r
+            return;\r
+        }\r
+\r
+        /* --------------------------------- 2.创建定时器 -------------------------------- */\r
+        g_timer = osTimerNew((osTimerFunc_t)CountDown_TimerCallback, osTimerPeriodic, NULL, NULL);\r
+        // 检查定时器创建是否成功\r
+        if (g_timer == NULL)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CountDownModel::CountDown_StartTimer Timer create failed!!");\r
+            return;\r
+        }\r
+\r
+        /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */\r
+        int tick = osMs2Tick(interval);\r
+\r
+        /* --------------------------------- 4.启动定时器 -------------------------------- */\r
+        // g_timerStartTimestamp = GetCurrentTimestamp(); // 假设GetCurrentTimestamp()是获取当前时间戳的函数\r
+        osStatus_t ret = osTimerStart(g_timer, tick);\r
+        /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 NULL -------------------- */\r
+        if (ret != osOK)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[CountDown_StartTimer] osTimerDelete failed, ret = %lx!!", ret);\r
+            if (g_timer != NULL)\r
+            {\r
+                ret = osTimerDelete(g_timer);\r
+            }\r
+            g_timer = NULL;\r
+            return;\r
+        }\r
+        return;\r
+    }\r
+\r
+    /*\r
+     * @brief 停止定时器\r
+     */\r
+    void CountDownModel::CountDown_StopTimer(void)\r
+    {\r
+        // 检查定时器是否存在\r
+        if (g_timer != NULL)\r
+        {\r
+            // 删除定时器并置为 NULL\r
+            osStatus_t ret = osTimerDelete(g_timer);\r
+            if (ret != osOK)\r
+            {\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScanTimerCallback osTimerDelete failed, ret = %lx!!", ret);\r
+            }\r
+            g_timer = NULL;\r
+            g_CountDownTimes = 0;\r
+        }\r
+    }\r
+    /*\r
+     * @brief 暂停定时器\r
+     */\r
+    void CountDownModel::CountDown_PauseTimer(void)\r
+    {\r
+        // 检查定时器是否存在\r
+        if (g_timer != NULL)\r
+        {\r
+            // 暂停定时器,但不删除它\r
+            osStatus_t ret = osTimerStop(g_timer);\r
+            if (ret != osOK)\r
+            {\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CountDown_PauseTimer osTimerStop failed, ret = %lx!!", ret);\r
+            }\r
+        }\r
+    }\r
+\r
+    /*\r
+     * @brief 恢复定时器\r
+     */\r
+    void CountDownModel::CountDown_ResumeTimer(uint32_t interval)\r
+    {\r
+        // 检查定时器是否存在\r
+        if (g_timer != NULL)\r
+        {\r
+            int tick = osMs2Tick(interval);\r
+            // 恢复定时器\r
+            osStatus_t ret = osTimerStart(g_timer, tick);\r
+            if (ret != osOK)\r
+            {\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CountDown_ResumeTimer osTimerStart failed, ret = %lx!!", ret);\r
+            }\r
+        }\r
+    }\r
+\r
 }\r
index 0d96461..e64fd1b 100644 (file)
@@ -24,7 +24,7 @@ namespace OHOS
 \r
     MainCountDownPresenter::~MainCountDownPresenter()\r
     {\r
-\r
+        CountDownModel::GetInstance()->CountDown_StopTimer();\r
         g_pMainCountDownPresenter = nullptr;\r
     }\r
 \r
@@ -163,6 +163,7 @@ namespace OHOS
         {\r
             CountDownModel::GetInstance()->SetCountDownTime("00:00:00");\r
             CountDownModel::GetInstance()->SetRingTime("");\r
+            MainCountDownView::GetInstance()->GetStartCountDownView()->GetPlayOrPauseToggleButton()->SetState(false);\r
             p_MainCountDownView->ChangeView(START_COUNTDOWN, MAIN_COUNTDOWN);\r
             return true;\r
         }\r
@@ -186,13 +187,15 @@ namespace OHOS
 \r
     bool MainCountDownPresenter::OnChange(UICheckBox::UICheckBoxState state)\r
     {\r
+        CountDownModel *p_CountDownModel = CountDownModel::GetInstance();\r
         switch (state)\r
         {\r
         case UICheckBox::SELECTED:\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "start countdown...");\r
-\r
+            p_CountDownModel->CountDown_StartTimer(COUNTDOWN_TIMER_DURATION);\r
+            p_CountDownModel->CountDown_ResumeTimer(COUNTDOWN_TIMER_DURATION);\r
+            break;\r
         case UICheckBox::UNSELECTED:\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "countdown pause...");\r
+            p_CountDownModel->CountDown_PauseTimer();\r
             break;\r
         default:\r
             break;\r
index 4f4bb9a..40e0096 100644 (file)
@@ -104,13 +104,13 @@ namespace OHOS
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "showCountDownTimelabel  is new fail!!");\r
                 return nullptr;\r
             }\r
-            showCountDownTimelabel->SetPosition(73, 138);\r
+            showCountDownTimelabel->SetPosition(33, 138, 400, 94);\r
             showCountDownTimelabel->SetStyle(STYLE_TEXT_FONT, 80);\r
             showCountDownTimelabel->SetStyle(STYLE_LINE_HEIGHT, 94);\r
             showCountDownTimelabel->SetText(CountDownModel::GetInstance()->GetCountDownTime().c_str());\r
-            showCountDownTimelabel->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);\r
+            showCountDownTimelabel->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE);\r
             showCountDownTimelabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);\r
-            showCountDownTimelabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 84);\r
+            showCountDownTimelabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 80);\r
             /* -------------------------------------------------------------------------- */\r
             vectorImage = new UIImageView();\r
             if (vectorImage == nullptr)\r
@@ -187,4 +187,9 @@ namespace OHOS
     {\r
         return showTheRingTime;\r
     }\r
+\r
+    UIToggleButton *StartCountDownView::GetPlayOrPauseToggleButton(void)\r
+    {\r
+        return play_or_pause_toggleButton;\r
+    }\r
 }
\ No newline at end of file
index 4922014..0a38795 100644 (file)
@@ -111,7 +111,7 @@ namespace OHOS
     {\r
 #if 0\r
         uint64_t currentTimestamp = GetCurrentTimestamp();\r
-        if ((currentTimestamp - g_timerStartTimestamp) >= 5999099) // 99分59秒99的毫秒数\r
+        if ((currentTimestamp - g_timerStartTimestamp) >= 5999990) // 99分59秒99的毫秒数\r
         {\r
             if (g_timer != NULL)\r
             {\r
@@ -161,13 +161,13 @@ namespace OHOS
         /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 NULL -------------------- */\r
         if (ret != osOK)\r
         {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScanTimerCallback osTimerDelete failed, ret = %lx!!", ret);\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[StopWatch_StartTimer]osTimerDelete failed, ret = %lx!!", ret);\r
             if (g_timer != NULL)\r
             {\r
                 ret = osTimerDelete(g_timer);\r
-                return;\r
             }\r
             g_timer = NULL;\r
+            return;\r
         }\r
         return;\r
     }\r