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