From 17c55fecef8270c9d802056ec07b5e8e112b3c49 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E7=BD=97=E6=AD=A3?= <1732036298@qq.com> Date: Wed, 26 Mar 2025 08:37:38 +0000 Subject: [PATCH] Merge #1711 into sdk650 from refs/changes/1711/head MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Code review from 罗正 * refs/changes/1711/head: (9 commits squashed) - 查找手机slice合并提交 - 计时器slice合并提交 - 日历slice合并提交 - 日程slice合并提交 - 订阅消息Topic文件提交 - 遥控拍照slice合并提交 - 呼吸训练slice合并提交 - Merge branch 'sdk650' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650 - 秒表slice合并提交 Signed-off-by: 罗正 <1732036298@qq.com> Merged-by: Caisking <3449750381@qq.com> CR-link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/1711 --- .../RespiratoryTrainingCompletedView.h | 73 +++ ...RespiratoryTrainingDurationSelectionView.h | 66 ++ .../include/RespiratoryTrainingModel.h | 49 ++ .../include/RespiratoryTrainingPresenter.h | 48 ++ .../include/RespiratoryTrainingView.h | 116 ++++ .../src/RespiratoryTrainingCompletedView.cpp | 338 ++++++++++ ...spiratoryTrainingDurationSelectionView.cpp | 229 +++++++ .../src/RespiratoryTrainingModel.cpp | 249 ++++++++ .../src/RespiratoryTrainingPresenter.cpp | 205 +++++++ .../src/RespiratoryTrainingView.cpp | 577 ++++++++++++++++++ .../include/MainStopWatchPresenter.h | 77 +++ .../stopwatch/include/MainStopWatchView.h | 82 +++ .../stopwatch/include/StopWatchAdapter.h | 47 ++ .../stopwatch/include/StopWatchItemView.h | 32 + .../stopwatch/include/StopWatchModel.h | 43 ++ .../include/StopWatchRecordCycleToLimitView.h | 39 ++ .../include/StopWatchRecordTimeToLimitView.h | 39 ++ .../stopwatch/src/MainStopWatchPresenter.cpp | 377 ++++++++++++ .../stopwatch/src/MainStopWatchView.cpp | 417 +++++++++++++ .../stopwatch/src/StopWatchAdapter.cpp | 83 +++ .../stopwatch/src/StopWatchItemView.cpp | 74 +++ .../nativeui/stopwatch/src/StopWatchModel.cpp | 210 +++++++ .../src/StopWatchRecordCycleToLimitView.cpp | 156 +++++ .../src/StopWatchRecordTimeToLimitView.cpp | 178 ++++++ .../config/target_config/brandy/config.py | 4 +- 25 files changed, 3806 insertions(+), 2 deletions(-) create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingCompletedView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingModel.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingPresenter.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingCompletedView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingDurationSelectionView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingModel.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingPresenter.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchPresenter.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchAdapter.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchItemView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchModel.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordCycleToLimitView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordTimeToLimitView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchPresenter.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchAdapter.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchItemView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchModel.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordCycleToLimitView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordTimeToLimitView.cpp diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingCompletedView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingCompletedView.h new file mode 100644 index 000000000..3fb267ad5 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingCompletedView.h @@ -0,0 +1,73 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-06-08 18:24:24 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-06-11 14:41:30 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/include/RespiratoryTrainingCompletedCompletedView.h + */ + +#ifndef RESPIRATORY_TRAINING_COMPLETED_VIEW_H +#define RESPIRATORY_TRAINING_COMPLETED_VIEW_H + + +#include "View.h" +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_label_button_ext.h" +#include "components/ui_image_view.h" + +namespace OHOS +{ + static constexpr int MAX_NUM = 3; + static constexpr const char *RTCLABELBUTTON = "RTCLabelButton"; + static constexpr const char *RTCVectorImagePath = "/user/res/RespiratoryTraining/RTCVector.bin"; + static constexpr const char *RTCGroupListImagePath = "/user/res/RespiratoryTraining/RTCGroupList.bin"; + class RespiratoryTrainingCompletedView + { + public: + struct LabelConfig + { + int16_t left; + int16_t top; + int16_t width; + int16_t height; + int16_t fontSize; // 字体大小 + int16_t lineHeigh; // 行高 + const char *text; + int16_t textId; + uint8_t lineBreakMode; // 断行模式。 + }; + + struct ImageConfig + { + int16_t x; + int16_t y; + int16_t w; + int16_t h; + }; + + RespiratoryTrainingCompletedView(); + ~RespiratoryTrainingCompletedView(); + static RespiratoryTrainingCompletedView *GetInstance(void); + UIScrollView *RespiratoryTrainingCompletedViewInit(void); + + private: + void ClearAll(void); + bool CreateRespiratoryTrainingCompletedScrollView(); + bool CreateRespiratoryTrainingCompletedLabelView(); + bool CreateRespiratoryTrainingCompletedImageView(); + bool CreateRespiratoryTrainingCompletedLabelButtonView(); + UILabelExt *LabelExtViewInit(const LabelConfig &labelconfig); + UILabel *LabelViewInit(const LabelConfig &labelconfig); + UIImageView *ImageViewInit(ImageConfig &imageconfig); + UIScrollView *ScrollView{nullptr}; + UILabelExt *Title{nullptr}; + UILabelExt *RespiratoryTrainingLabel{nullptr}; + UIImageView *RespiratoryTrainingImage{nullptr}; + UILabelExt *RTCStaticLabelView[MAX_NUM]{nullptr}; + UILabel *RTCDynamicLabelView[MAX_NUM]{nullptr}; + UIImageView *RTCImageView[MAX_NUM]{nullptr}; + UILabelButtonExt *RTCLabelButton{nullptr}; + }; +} +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h new file mode 100644 index 000000000..7955be9d3 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h @@ -0,0 +1,66 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-09-29 17:51:20 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-10-04 17:47:43 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h + */ +#ifndef RESPIRATORY_TRAINING_DURATION_SELECTION_VIEW_H +#define RESPIRATORY_TRAINING_DURATION_SELECTION_VIEW_H +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_label_button_ext.h" + +#include "components/ui_image_view.h" +namespace OHOS +{ +#define MAX_NUM_TRAINING_DURATION 5 + + static constexpr const char *RESPIRATORYTRAINING_DURATIONSELECTION_VIEW = "RespiratoryTrainingDurationSelectionView"; + static constexpr const char *TRAINING_DURATION_ONE_MIN = "training_duration_one_min"; + static constexpr const char *TRAINING_DURATION_TWO_MIN = "training_duration_two_min"; + static constexpr const char *TRAINING_DURATION_THREE_MIN = "training_duration_three_min"; + static constexpr const char *TRAINING_DURATION_FOUR_MIN = "training_duration_four_min"; + static constexpr const char *TRAINING_DURATION_FIVE_MIN = "training_duration_five_min"; + class RespiratoryTrainingDurationSelectionView + { + public: + struct LabelButtonConfig + { + int16_t left; + int16_t top; + int16_t width; + int16_t height; + const char *viewId; + }; + struct LabelConfig + { + int16_t left; + int16_t top; + int16_t width; + int16_t height; + int16_t fontSize; + int16_t lineHeigh; + const char *text; + int16_t textId; + uint8_t lineBreakMode; + }; + RespiratoryTrainingDurationSelectionView(/* args */); + ~RespiratoryTrainingDurationSelectionView(); + static RespiratoryTrainingDurationSelectionView *GetInstance(void); + UIScrollView *RespiratoryTrainingDurationSelectionViewInit(void); + void UpdateRespiratoryTrainingDurationSelectionView(void); + + private: + UILabelExt *LabelViewinit(LabelConfig &labelconfig); + UILabelButtonExt *LabelButtonViewInit(LabelButtonConfig &labelbuttonconfig); + void ClearAll(void); + UIScrollView *scrollView = nullptr; + UILabelExt *TitleLabel = nullptr; // 标题 + UILabelExt *DurationLabel[MAX_NUM_TRAINING_DURATION]{nullptr}; // 亮屏时长标签 + UILabelButtonExt *DurationButton[MAX_NUM_TRAINING_DURATION]{nullptr}; // 放置组件的按钮 + UIImageView *temp{nullptr}; + }; + +} +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingModel.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingModel.h new file mode 100644 index 000000000..a6ad2c5d6 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingModel.h @@ -0,0 +1,49 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-06-11 16:26:13 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-10-09 12:22:31 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/include/RespiratoryTrainingModel.h + */ +#ifndef RESPIRATORY_TRAINING_MODEL_H +#define RESPIRATORY_TRAINING_MODEL_H + +#include +#include +#include "string" +namespace OHOS +{ + class RespiratoryTrainingModel + { + public: + static RespiratoryTrainingModel &GetInstance(void); + void AddRespiratoryTrainingTimes(void); + std::string GetRespiratoryTrainingTotalTime(void); + int GetAverageHeartRate(void); + void calculateHeartrateTotal(void); + void ResumeStatus(); + + void RT_StartTimer(uint64_t interval); + void RT_StopTimer(void); + + int GetRespiratoryTrainingSelectTime(); + void SetRespiratoryTrainingSelectTime(int time); + uint64_t GetRespiratoryTrainingTime(); + void ClearTotalRespiratoryTrainingTime(void); + + private: + RespiratoryTrainingModel(); + ~RespiratoryTrainingModel(); + RespiratoryTrainingModel(const RespiratoryTrainingModel &) = delete; + RespiratoryTrainingModel &operator=(const RespiratoryTrainingModel &) = delete; + + int RespiratoryTrainingTimes{0}; // 呼吸训练次数 + int RespiratoryTrainingTime{0}; + std::string HeartRateValue{nullptr}; + int count{0}; + float heartTotal{0}; + int selectTime{1}; + }; +} + +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingPresenter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingPresenter.h new file mode 100644 index 000000000..913e5fe12 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingPresenter.h @@ -0,0 +1,48 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-06-08 09:36:33 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-10-05 12:29:42 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/include/RespiratoryTrainingPresenter.h + */ + +#ifndef RESPIRATORY_TRAINING_PRESENTER_H +#define RESPIRATORY_TRAINING_PRESENTER_H + +#include "Presenter.h" +#include "View.h" + +namespace OHOS +{ + + class RespiratoryTrainingView; + class RespiratoryTrainingPresenter : public Presenter, + public UIView::OnClickListener, + public RootView::OnKeyActListener, + public UIView::OnDragListener + { + public: + RespiratoryTrainingPresenter(); + virtual ~RespiratoryTrainingPresenter(); + + void OnStart() override; + void OnPause() override; + void OnResume() override; + void OnStop() override; + + static RespiratoryTrainingPresenter *GetInstance(); + + int GetRespiratoryTrainingSelectTime(); + std::string GetRespiratoryTrainingSelectTime1(); + + private: + bool OnClick(UIView &view, const ClickEvent &event) override; + bool OnDrag(UIView &view, const DragEvent &event) override; + bool OnDragEnd(UIView &view, const DragEvent &event) override; + bool OnKeyAct(UIView &view, const KeyEvent &event) override; // 增加按键事件 + + bool X_DRAG_FLAG{false}; + }; +} + +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingView.h new file mode 100644 index 000000000..09d1549a7 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/include/RespiratoryTrainingView.h @@ -0,0 +1,116 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-06-08 09:36:01 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2025-02-24 17:35:35 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/include/RespiratoryTrainingView.h + */ + +#ifndef RESPIRATORY_TRAINING_VIEW_H +#define RESPIRATORY_TRAINING_VIEW_H + + +#include "View.h" +#include "components/ui_label_ext.h" +#include +#include "components/ui_image_animator.h" +#include "components/ui_image_view.h" +#include "components/root_view.h" +#include "hal_tick.h" +#include "components/ui_scroll_view.h" +#include "respiratorytraining/include/RespiratoryTrainingCompletedView.h" +#include "respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h" + +namespace OHOS +{ + typedef enum + { + RESPIRATORYTRAINING = 0, + RESPIRATORYTRAININGCOMPLETED, + RESPIRATORY_TRAINING_DURATION_SELECTION, // 训练时长选择 + MAX_RESPIRATORYTRAININGID, + } RESPIRATORYTRAININGVIEWID; + + class RespiratoryTrainingCallback : public AnimatorCallback + { + public: + explicit RespiratoryTrainingCallback(UIImageView *img) : img_(img) {} + ~RespiratoryTrainingCallback() override {} + void Callback(UIView *view) override; + void SetTextView(UILabelExt *view) + { + breath = view; + } + + uint32_t startTimestamp = 0; + + private: + UIImageView *img_ = nullptr; + UILabelExt *breath = nullptr; + bool isBreathIn = false; + int16_t angle = 0; + int16_t step = -1; + float scale = 0; + uint16_t curTime = 0; + uint16_t prepareTiem = 0; + uint16_t durationTime = 5 * 1000; // 5000: means 5000ms + int16_t startVal = durationTime; + int16_t endVal = durationTime / 2; // 2: half + bool isprepare{false}; + int prepare_count = 0; + }; + + static constexpr int RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_X = 193; + static constexpr int RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_Y = 110; + static constexpr int RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_W = 80; + static constexpr int RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_H = 80; + static constexpr int RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_TIMEOFUPDATE = 100; + static constexpr int RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES = 25; // 呼吸训练动画帧数 + static ImageAnimatorInfo RespiratoryTrainingImageInfo[RESPIRATORY_TRAINING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES]; + + class RespiratoryTrainingPresenter; + class RespiratoryTrainingView : public View, public UIView::OnClickListener + { + + public: + RespiratoryTrainingView(); + virtual ~RespiratoryTrainingView(); + static RespiratoryTrainingView *GetInstance(void); + bool ClickFunc(int16_t interface); + void ChangeView(int16_t hideView, int16_t showView); + bool ChangeRespiratoryTrainingView(int16_t thisView); + bool ChangeRespiratoryTrainingCompletedView(int16_t thisView); + bool ChangeRespiratoryTrainingDurationSelectionView(int16_t thisView); + Animator *GetRespiratoryTrainingAnimator_(); + bool StartRespiratoryTraining(); + void OnStart() override; + bool OnClick(UIView &view, const ClickEvent &event) override; + + private: + void RespiratoryTrainingViewInit(void); + void ClearAll(void); + bool InitRespiratoryTrainingElements(); + bool InitRespiratoryTrainingElements2(); + bool InitRespiratoryTrainingCallBackAndAnimator(); + bool InitRespiratoryTrainingScrollView(); + void HandStartRespiratoryTraining(); + UIScrollView *RespiratoryTrainingScrollView[MAX_RESPIRATORYTRAININGID]{nullptr}; + RespiratoryTrainingCompletedView *p_RespiratoryTrainingCompletedView{nullptr}; + RespiratoryTrainingDurationSelectionView *p_RespiratoryTrainingDurationSelectionView{nullptr}; + RespiratoryTrainingCallback *RespiratoryTrainingCallBack_ = nullptr; + Animator *RespiratoryTrainingAnimator_ = nullptr; + UIImageView *RespiratoryTrainingImg_ = nullptr; + UILabelExt *RespiratoryTrainingStartNote_ = nullptr; + UILabelExt *RespiratoryTrainingLabel_ = nullptr; + bool animateStart_ = false; + /* -------------------------------------------------------------------------- */ + UILabelExt *titlelabel{nullptr}; // 标题 + UILabelExt *TrainingDurationSelectiontitlelabel{nullptr}; // 选择的训练时长 + UIImageView *Image{nullptr}; + UILabelButton *RespiratoryTrainingStartButton = nullptr; // 训练开始按钮 + UILabelExt *RespiratoryTrainingStartLabel = nullptr; // 训练开始标签 + /* -------------------------------------------------------------------------- */ + }; + +} +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingCompletedView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingCompletedView.cpp new file mode 100644 index 000000000..962b347da --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingCompletedView.cpp @@ -0,0 +1,338 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-05-07 11:25:58 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2025-02-25 15:09:29 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/RespiratoryTrainingCompleted/src/RespiratoryTrainingCompletedView.cpp + */ + +#include "respiratorytraining/include/RespiratoryTrainingCompletedView.h" +#include "wearable_log.h" +#include "ui_resource_string.h" +#include "respiratorytraining/include/RespiratoryTrainingPresenter.h" +#include "common/image_cache_manager.h" +#include "respiratorytraining/include/RespiratoryTrainingModel.h" + +namespace OHOS +{ + + static RespiratoryTrainingCompletedView *g_pRespiratoryTrainingCompletedView{nullptr}; + + RespiratoryTrainingCompletedView::RespiratoryTrainingCompletedView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::RespiratoryTrainingCompletedView"); + g_pRespiratoryTrainingCompletedView = this; + } + + RespiratoryTrainingCompletedView::~RespiratoryTrainingCompletedView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::~RespiratoryTrainingCompletedView"); + ClearAll(); + g_pRespiratoryTrainingCompletedView = nullptr; + } + + RespiratoryTrainingCompletedView *RespiratoryTrainingCompletedView::GetInstance() + { + return g_pRespiratoryTrainingCompletedView; + } + + void RespiratoryTrainingCompletedView::ClearAll(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::ClearAll Start!!"); + if (ScrollView != nullptr) + { + ScrollView->RemoveAll(); + ImageCacheManager::GetInstance().UnloadSingleRes(RTCVectorImagePath); + ImageCacheManager::GetInstance().UnloadSingleRes(RTCGroupListImagePath); + + if (Title != nullptr) + { + delete Title; + Title = nullptr; + } + + if (RespiratoryTrainingImage != nullptr) + { + delete RespiratoryTrainingImage; + RespiratoryTrainingImage = nullptr; + } + + if (RespiratoryTrainingLabel != nullptr) + { + delete RespiratoryTrainingLabel; + RespiratoryTrainingLabel = nullptr; + } + for (int i = 0; i < MAX_NUM; i++) + { + if (RTCStaticLabelView[i] != nullptr) + { + delete RTCStaticLabelView[i]; + RTCStaticLabelView[i] = nullptr; + } + + if (RTCDynamicLabelView[i] != nullptr) + { + delete RTCDynamicLabelView[i]; + RTCDynamicLabelView[i] = nullptr; + } + + if (RTCImageView[i] != nullptr) + { + delete RTCImageView[i]; + RTCImageView[i] = nullptr; + } + } + + if (RTCLabelButton != nullptr) + { + delete RTCLabelButton; + RTCLabelButton = nullptr; + } + + delete ScrollView; + ScrollView = nullptr; + } + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::ClearAll End!!"); + } + + UILabelExt *RespiratoryTrainingCompletedView::LabelExtViewInit(const LabelConfig &labelconfig) + { + UILabelExt *label = new UILabelExt(); + if (label == nullptr) + { + return nullptr; + } + label->SetPosition(labelconfig.left, labelconfig.top, labelconfig.width, labelconfig.height); // 位置大小 + label->SetStyle(STYLE_TEXT_FONT, labelconfig.fontSize); // 字体大小 + label->SetStyle(STYLE_LINE_HEIGHT, labelconfig.lineHeigh); // 字体行高 + label->SetTextId(labelconfig.textId); // 内容 + label->SetLineBreakMode(labelconfig.lineBreakMode); // 断行模式。 + label->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, labelconfig.fontSize); + return label; + } + + UILabel *RespiratoryTrainingCompletedView::LabelViewInit(const LabelConfig &labelconfig) + { + UILabel *label = new UILabel(); + if (label == nullptr) + { + return nullptr; + } + label->SetPosition(labelconfig.left, labelconfig.top, labelconfig.width, labelconfig.height); // 位置大小 + label->SetStyle(STYLE_TEXT_FONT, labelconfig.fontSize); // 字体大小 + label->SetStyle(STYLE_LINE_HEIGHT, labelconfig.lineHeigh); // 字体行高 + label->SetText(labelconfig.text); // 内容 + label->SetLineBreakMode(labelconfig.lineBreakMode); // 断行模式。 + label->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, labelconfig.fontSize); + return label; + } + + UIImageView *RespiratoryTrainingCompletedView::ImageViewInit(ImageConfig &imageconfig) + { + UIImageView *Image = new UIImageView(); + if (Image == nullptr) + { + return nullptr; + } + Image->SetPosition(imageconfig.x, imageconfig.y, imageconfig.w, imageconfig.h); + return Image; + } + + bool RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedScrollView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedScrollView"); + ScrollView = new UIScrollView(); + if (ScrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScrollView new fail!"); + return false; + } + ScrollView->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight()); + ScrollView->SetScrollBlankSize(75); + ScrollView->SetReboundSize(35); + ScrollView->SetHorizontalScrollState(false); + ScrollView->SetTouchable(true); + ScrollView->SetDraggable(true); + ScrollView->RequestFocus(); + ScrollView->SetRotateFactor(1.0); + + return true; + } + + bool RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedLabelView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedLabelView"); + /* ---------------------------------- Title --------------------------------- */ + LabelConfig labelconfig = { + .left = 83, + .top = 52, + .width = 300, + .height = 35, + .fontSize = 30, + .lineHeigh = 35, + .textId = STR_TRAINING_COMPLETE, // 训练完成 + .lineBreakMode = UILabel::LINE_BREAK_MARQUEE, + }; + Title = LabelExtViewInit(labelconfig); + if (nullptr == Title) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Title is nullptr!"); + return false; + } + Title->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + ScrollView->Add(Title); + /* ------------------------ RespiratoryTrainingLabel ------------------------ */ + labelconfig.left = 147; + labelconfig.top = 150; + labelconfig.width = 240; + labelconfig.textId = STR_BREATH_TRAINING; // 呼吸训练 + RespiratoryTrainingLabel = LabelExtViewInit(labelconfig); + if (nullptr == RespiratoryTrainingLabel) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingLabel is nullptr!"); + return false; + } + ScrollView->Add(RespiratoryTrainingLabel); + /* -------------------------------------------------------------------------- */ + int y1 = 248, y2 = 286; + const int textId[MAX_NUM] = {STR_THIS_BREATH, STR_MEAN_HEART_RATE_MIN, STR_TODAYS_BREATHING_TRAINING}; + int value = RespiratoryTrainingModel::GetInstance().GetAverageHeartRate(); + std::string select_time; + if (RespiratoryTrainingPresenter::GetInstance()) + { + select_time = RespiratoryTrainingPresenter::GetInstance()->GetRespiratoryTrainingSelectTime1(); + } + std::string heartRateValue = (value == 0 ? "--" : std::to_string(value)); + std::string trainingTotalTime = RespiratoryTrainingModel::GetInstance().GetRespiratoryTrainingTotalTime(); + const char *text[MAX_NUM] = {select_time.c_str(), heartRateValue.c_str(), trainingTotalTime.c_str()}; + OHOS::ColorType RTCDynamicLabelTextColor[MAX_NUM] = { + Color::GetColorFromRGBA(0x1d, 0xda, 0xc4, 0xff), + Color::GetColorFromRGBA(0xff, 0x5a, 0x36, 0xff), + Color::GetColorFromRGBA(0xff, 0x8a, 0x36, 0xff), + }; + for (int i = 0; i < MAX_NUM; i++) + { + labelconfig.left = 138; + labelconfig.top = y1 + 130 * i; + labelconfig.width = 240; + labelconfig.height = 35; + labelconfig.fontSize = 30; + labelconfig.lineHeigh = 35; + labelconfig.textId = textId[i]; + labelconfig.lineBreakMode = UILabel::LINE_BREAK_MARQUEE; + RTCStaticLabelView[i] = LabelExtViewInit(labelconfig); + if (nullptr == RTCStaticLabelView[i]) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RTCStaticLabelView[%d] is nullptr!", i); + return false; + } + RTCStaticLabelView[i]->SetTextColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0x7f)); + ScrollView->Add(RTCStaticLabelView[i]); + /* -------------------------------------------------------------------------- */ + labelconfig.left = 138; + labelconfig.top = y2 + 130 * i; + labelconfig.height = 47; + labelconfig.fontSize = 40; + labelconfig.lineHeigh = 47; + labelconfig.text = text[i]; + RTCDynamicLabelView[i] = LabelViewInit(labelconfig); + if (nullptr == RTCDynamicLabelView[i]) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RTCDynamicLabelView[%d] is nullptr!", i); + return false; + } + RTCDynamicLabelView[i]->SetTextColor(RTCDynamicLabelTextColor[i]); + RTCDynamicLabelView[i]->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, 30); + ScrollView->Add(RTCDynamicLabelView[i]); + } + return true; + } + + bool RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedImageView() + { + RespiratoryTrainingImage = new UIImageView(); + if (RespiratoryTrainingImage == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingImage is nullptr!!"); + return false; + } + RespiratoryTrainingImage->SetPosition(61, 122, 90, 90); + RespiratoryTrainingImage->SetAutoEnable(false); + RespiratoryTrainingImage->SetResizeMode(UIImageView::CENTER); + ImageInfo *imgInfo = ImageCacheManager::GetInstance().LoadSingleRes(RTCVectorImagePath); + if (imgInfo == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Load image failed!"); + return false; + } + RespiratoryTrainingImage->SetSrc(imgInfo); + ScrollView->Add(RespiratoryTrainingImage); + /* -------------------------------------------------------------------------- */ + ImageConfig imageconfig = { + .x = 89, + .y = 212, + .w = 42, + .h = 130, + }; + // 加载呼吸训练Vector图片 + imgInfo = ImageCacheManager::GetInstance().LoadSingleRes(RTCGroupListImagePath); + for (int i = 0; i < MAX_NUM; i++) + { + imageconfig.y = 212 + (i * 130); + RTCImageView[i] = ImageViewInit(imageconfig); + if (RTCImageView[i] == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RTCImageView[%d] is nullptr!", i); + return false; + } + RTCImageView[i]->SetSrc(imgInfo); + ScrollView->Add(RTCImageView[i]); + } + return true; + } + + bool RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedLabelButtonView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedLabelButtonView"); + RTCLabelButton = new UILabelButtonExt(); + if (RTCLabelButton == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RTCLabelButton is nullptr!"); + return false; + } + RTCLabelButton->SetPosition(43, 622); + RTCLabelButton->Resize(380, 100); + RTCLabelButton->SetViewId(RTCLABELBUTTON); + RTCLabelButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); + // RTCLabelButton->SetText("关闭"); + RTCLabelButton->SetTextId(STR_CLOSE); + RTCLabelButton->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + RTCLabelButton->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff000000, UIButton::PRESSED); + RTCLabelButton->SetStyleForState(STYLE_BORDER_COLOR, 0xffffffff, UIButton::PRESSED); + RTCLabelButton->SetStyleForState(STYLE_BORDER_OPA, 0x00, UIButton::PRESSED); + UIView::OnClickListener *labelButtonClick = static_cast(RespiratoryTrainingPresenter::GetInstance()); + if (labelButtonClick == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "labelButtonClick is nullptr!"); + return false; + } + RTCLabelButton->SetOnClickListener(labelButtonClick); + ScrollView->Add(RTCLabelButton); + return true; + } + + // 呼吸训练完成视图初始化 + UIScrollView *RespiratoryTrainingCompletedView::RespiratoryTrainingCompletedViewInit(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::RespiratoryTrainingCompletedViewInit"); + if (!CreateRespiratoryTrainingCompletedScrollView() || !CreateRespiratoryTrainingCompletedLabelView() || + !CreateRespiratoryTrainingCompletedImageView() || !CreateRespiratoryTrainingCompletedLabelButtonView()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedViewInit fail!!"); + return nullptr; + } + return ScrollView; + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingDurationSelectionView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingDurationSelectionView.cpp new file mode 100644 index 000000000..eea5598b0 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingDurationSelectionView.cpp @@ -0,0 +1,229 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-09-29 15:57:59 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-11-05 14:40:12 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/src/RespiratoryTrainingDurationSelectionView.cpp + */ +#include "respiratorytraining/include/RespiratoryTrainingDurationSelectionView.h" +#include "respiratorytraining/include/RespiratoryTrainingPresenter.h" +#include "respiratorytraining/include/RespiratoryTrainingModel.h" +#include "wearable_log.h" +#include "UiConfig.h" +#include "dock/focus_manager.h" +#include "ui_resource_string.h" +namespace OHOS +{ + + static RespiratoryTrainingDurationSelectionView *g_pRespiratoryTrainingDurationSelectionView{nullptr}; + RespiratoryTrainingDurationSelectionView::RespiratoryTrainingDurationSelectionView(/* args */) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingDurationSelectionView::RespiratoryTrainingDurationSelectionView"); + g_pRespiratoryTrainingDurationSelectionView = this; + } + + RespiratoryTrainingDurationSelectionView::~RespiratoryTrainingDurationSelectionView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingDurationSelectionView::~RespiratoryTrainingDurationSelectionView"); + ClearAll(); + g_pRespiratoryTrainingDurationSelectionView = nullptr; + } + + RespiratoryTrainingDurationSelectionView *RespiratoryTrainingDurationSelectionView::GetInstance(void) + { + return g_pRespiratoryTrainingDurationSelectionView; + } + + void RespiratoryTrainingDurationSelectionView::ClearAll(void) + { + if (scrollView) + { + scrollView->RemoveAll(); + delete TitleLabel; + TitleLabel = nullptr; + for (int i = 0; i < MAX_NUM_TRAINING_DURATION; i++) + { + delete DurationLabel[i]; + DurationLabel[i] = nullptr; + delete DurationButton[i]; + DurationButton[i] = nullptr; + } + delete temp; + temp = nullptr; + delete scrollView; + scrollView = nullptr; + } + } + + UILabelExt *RespiratoryTrainingDurationSelectionView::LabelViewinit(LabelConfig &labelconfig) + { + UILabelExt *label = new UILabelExt(); + if (label == nullptr) + { + return nullptr; + } + label->SetPosition(labelconfig.left, labelconfig.top, labelconfig.width, labelconfig.height); + label->SetStyle(STYLE_TEXT_FONT, labelconfig.fontSize); + label->SetStyle(STYLE_LINE_HEIGHT, labelconfig.lineHeigh); + label->SetTextId(labelconfig.textId); + // label->SetText(labelconfig.text); + label->SetLineBreakMode(labelconfig.lineBreakMode); + label->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + label->SetRollSpeed(23); + label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, labelconfig.fontSize); + return label; + } + + UILabelButtonExt *RespiratoryTrainingDurationSelectionView::LabelButtonViewInit(LabelButtonConfig &labelbuttonconfig) + { + UILabelButtonExt *labelButton = new UILabelButtonExt(); + if (labelButton == nullptr) + { + return nullptr; + } + labelButton->SetPosition(labelbuttonconfig.left, labelbuttonconfig.top); + labelButton->Resize(labelbuttonconfig.width, labelbuttonconfig.height); + labelButton->SetViewId(labelbuttonconfig.viewId); + labelButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); + labelButton->SetImagePosition(300, 30); + labelButton->SetImageSrc(PNG_CHECKBOX_OFF_IMAGE, PNG_CHECKBOX_OFF_IMAGE); + // labelButton->SetTextId(labelbuttonconfig.textId); + // labelButton->SetAlign(TEXT_ALIGNMENT_LEFT); + // labelButton->SetLabelPosition(100, 0); + // labelButton->SetFont(DEFAULT_VECTOR_FONT_FILENAME, labelbuttonconfig.fontSize); + // labelButton->SetStyle(STYLE_LINE_HEIGHT, labelbuttonconfig.lineHeigh); + labelButton->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff000000, UIButton::PRESSED); + return labelButton; + } + + UIScrollView *RespiratoryTrainingDurationSelectionView::RespiratoryTrainingDurationSelectionViewInit(void) + { + if (scrollView == nullptr) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ThemeStyleView::InitThemeStyleScrollView"); + scrollView = new UIScrollView(); + if (scrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "scrollView new fail!"); + return nullptr; + } + scrollView->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight()); + scrollView->SetViewId(RESPIRATORYTRAINING_DURATIONSELECTION_VIEW); + scrollView->SetScrollBlankSize(30); + scrollView->SetReboundSize(30); + scrollView->SetDirection(1); + scrollView->SetTouchable(true); + scrollView->SetDraggable(true); + scrollView->SetThrowDrag(true); // 设置手指抬起屏幕后是否继续滚动。 + scrollView->SetMaxScrollDistance(1000); // 设置手指抬起屏幕后的最大滚动距离。 + scrollView->SetSwipeACCLevel(200); /*设置手指抬起屏幕后的补偿距离。*/ + scrollView->SetRotateFactor(1.0); + FocusManager::GetInstance()->RequestFocus(scrollView); + FocusManager::GetInstance()->RequestFocusByDirection(FOCUS_DIRECTION_UP); + UIView::OnDragListener *dragListener = static_cast(RespiratoryTrainingPresenter::GetInstance()); + if (dragListener == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "dragListener is nullptr!"); + return nullptr; + } + scrollView->SetOnDragListener(dragListener); + /* -------------------------------------------------------------------------- */ + TitleLabel = new UILabelExt(); + if (TitleLabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TitleLabel new fail!"); + return nullptr; + } + TitleLabel->SetPosition(83, 50, 300, 35); + TitleLabel->SetTextId(STR_DURATION_SETTINGS); // 时长设置 + TitleLabel->SetStyle(STYLE_TEXT_FONT, 30); + TitleLabel->SetStyle(STYLE_LINE_HEIGHT, 35); + TitleLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + TitleLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + TitleLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + scrollView->Add(TitleLabel); + /* -------------------------------------------------------------------------- */ + UIView::OnClickListener *clickListener = static_cast(RespiratoryTrainingPresenter::GetInstance()); + if (clickListener == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "clickListener is nullptr!"); + return nullptr; + } + LabelButtonConfig labelbuttonconfig; + const char *viewId[MAX_NUM_TRAINING_DURATION] = {TRAINING_DURATION_ONE_MIN, TRAINING_DURATION_TWO_MIN, TRAINING_DURATION_THREE_MIN, TRAINING_DURATION_FOUR_MIN, TRAINING_DURATION_FIVE_MIN}; + for (int i = 0; i < MAX_NUM_TRAINING_DURATION; i++) + { + labelbuttonconfig.left = 43; + labelbuttonconfig.top = 120 + 120 * i; + labelbuttonconfig.width = 380; + labelbuttonconfig.height = 100; + labelbuttonconfig.viewId = viewId[i]; + DurationButton[i] = LabelButtonViewInit(labelbuttonconfig); + if (DurationButton[i] == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DurationButton[%d] is nullptr", i); + return nullptr; + } + DurationButton[i]->SetOnClickListener(clickListener); + scrollView->Add(DurationButton[i]); + } + /* -------------------------------------------------------------------------- */ + int16_t textId[MAX_NUM_TRAINING_DURATION] = {STR_1_MIN, STR_2_MIN,STR_3_MIN,STR_4_MIN, STR_5_MIN}; + // const char *text[MAX_NUM_TRAINING_DURATION] = {"1分钟", "2分钟", "3分钟", "4分钟", "5分钟"}; + LabelConfig labelConfig = { + .left = 103, + .top = 153, + .width = 210, + .height = 35, + .fontSize = 30, + .lineHeigh = 35, + .textId = 0, + .lineBreakMode = UILabel::LINE_BREAK_OSCILLATION, + }; + for (int16_t i = 0; i < MAX_NUM_TRAINING_DURATION; i++) + { + labelConfig.top = 153 + 120 * i; + labelConfig.textId = textId[i]; + // labelConfig.text = text[i]; + DurationLabel[i] = LabelViewinit(labelConfig); + if (DurationLabel[i] == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DurationLabel[%d] is nullptr", i); + return nullptr; + } + scrollView->Add(DurationLabel[i]); + } + /* -------------------------------------------------------------------------- */ + if (temp == nullptr) + { + temp = new UIImageView(); + if (temp == nullptr) + { + return nullptr; + } + int y = DurationButton[MAX_NUM_TRAINING_DURATION - 1]->GetY() + DurationButton[MAX_NUM_TRAINING_DURATION - 1]->GetHeight(); + temp->SetPosition(43, y, 380, 40); + temp->SetVisible(false); + scrollView->Add(temp); + } + } + UpdateRespiratoryTrainingDurationSelectionView(); + return scrollView; + } + + void RespiratoryTrainingDurationSelectionView::UpdateRespiratoryTrainingDurationSelectionView(void) + { + for (int i = 0; i < MAX_NUM_TRAINING_DURATION; i++) + { + if (i == RespiratoryTrainingModel::GetInstance().GetRespiratoryTrainingSelectTime() - 1) + { + DurationButton[i]->SetImageSrc(PNG_CHECKBOX_ON_IMAGE, PNG_CHECKBOX_ON_IMAGE); + } + else + { + DurationButton[i]->SetImageSrc(PNG_CHECKBOX_OFF_IMAGE, PNG_CHECKBOX_OFF_IMAGE); + } + DurationButton[i]->Invalidate(); + } + } +} diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingModel.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingModel.cpp new file mode 100644 index 000000000..044b28e35 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingModel.cpp @@ -0,0 +1,249 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-06-11 16:26:20 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-11-05 14:40:25 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/respiratorytraining/src/RespiratoryTrainingModel.cpp + */ +#include "respiratorytraining/include/RespiratoryTrainingModel.h" +#include "wearable_log.h" +#include +#include +#include +#include +#include +#include "respiratorytraining/include/RespiratoryTrainingView.h" +#include +#include "gfx_utils/mem_check.h" +#include "ConfigModel.h" + +#include +#include +#include +#include +#include +#include +#include +#ifdef FD230_650 +#include "heartrate/include/HeartModel.h" +#endif +namespace OHOS +{ + // 声明定时器变量 + static osTimerId_t g_timer = NULL; + static constexpr uint64_t ONE_MIN = 60000 * 1; // 1分钟 + static constexpr uint64_t TWO_MIN = 60000 * 2; // 2分钟 + static constexpr uint64_t THREE_MIN = 60000 * 3; // 3分钟 + static constexpr uint64_t FOUR_MIN = 60000 * 4; // 4分钟 + static constexpr uint64_t FIVE_MIN = 60000 * 5; // 5分钟 + + RespiratoryTrainingModel::RespiratoryTrainingModel() {} + + RespiratoryTrainingModel::~RespiratoryTrainingModel() {} + + RespiratoryTrainingModel &RespiratoryTrainingModel::GetInstance() + { + static RespiratoryTrainingModel instance; + return instance; + } + + // 获取训练时长,单位min + int RespiratoryTrainingModel::GetRespiratoryTrainingSelectTime() + { + return ConfigModel::GetInstance()->get_configData_int(ConfigModel::CONFIGMODEL_ITEM_RESPIRATORY_TRAINING_DURATION_SELECTION); + } + + // 设置训练时长,单位min + void RespiratoryTrainingModel::SetRespiratoryTrainingSelectTime(int time) + { + ConfigModel::GetInstance()->set_condigData_Int(ConfigModel::CONFIGMODEL_ITEM_RESPIRATORY_TRAINING_DURATION_SELECTION, time); + } + + uint64_t RespiratoryTrainingModel::GetRespiratoryTrainingTime() + { + int time = RespiratoryTrainingModel::GetInstance().GetRespiratoryTrainingSelectTime(); + uint64_t time_; + switch (time) + { + case 1: + time_ = ONE_MIN; + break; + case 2: + time_ = TWO_MIN; + break; + case 3: + time_ = THREE_MIN; + break; + case 4: + time_ = FOUR_MIN; + break; + case 5: + time_ = FIVE_MIN; + break; + default: + time_ = ONE_MIN; + break; + } + return time_; + } + + // 每进行一次呼吸训练,呼吸训练次数自加1 + void RespiratoryTrainingModel::AddRespiratoryTrainingTimes() + { + RespiratoryTrainingTimes += 1; + } + + // 获取呼吸训练总时间 + std::string RespiratoryTrainingModel::GetRespiratoryTrainingTotalTime(void) + { + RespiratoryTrainingTime += GetRespiratoryTrainingSelectTime(); + return (std::to_string(RespiratoryTrainingTime) + "min"); + } + + // 获取平均心率值 + int RespiratoryTrainingModel::GetAverageHeartRate(void) + { + if (count != 0) + { + return heartTotal / count; + } + return 0; + } + + // 清除当日的呼吸训练时间 + void RespiratoryTrainingModel::ClearTotalRespiratoryTrainingTime(void) + { + if (RespiratoryTrainingTime != 0) + { + RespiratoryTrainingTime = 0; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ClearTotalRespiratoryTrainingTime success!!"); + } + } + + void RespiratoryTrainingModel::calculateHeartrateTotal(void) + { + // 获取当前时间(以微秒为单位) + uint32_t currentTime = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + + // 记录和检查上一次调用的时间 + static uint32_t lastCallTime = 0; + if (currentTime - lastCallTime < 1000000) + { + // 小于1秒 + return; + } + lastCallTime = currentTime; // 更新最后调用时间 + +#ifdef FD230_650 + uint16_t heartrate = HeartModel::GetInstance()->GetShowHeartdata(); + + if (heartrate != 0) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "heartrate = %d", heartrate); + heartTotal += heartrate; + count++; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "heartTotal = %0.f,count = %d,h_rate = %d", heartTotal, count, heartrate); + } +#endif + } + + void RespiratoryTrainingModel::ResumeStatus() + { + heartTotal = 0; + count = 0; +#ifdef FD230_650 + HeartModel::GetInstance()->Heart_Control(HeartState::End, HeartCheck::INITIATIVE); // 关闭心率检测 +#endif + uapi_dev_runtime_set_respiratory_training_status(0); // 如果直接退出也要设置为0 + } + /* -------------------------------------------------------------------------- */ + /*定时器到期时的处理*/ + static void RT_TimerCallbackProc(int data) + { + RespiratoryTrainingView *p_RespiratoryTrainingView = RespiratoryTrainingView::GetInstance(); + if (p_RespiratoryTrainingView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "p_RespiratoryTrainingView is nullptr!!"); + return; + } + uapi_dev_runtime_set_respiratory_training_status(0); // 训练结束runtime设置为0 + RespiratoryTrainingModel::GetInstance().RT_StopTimer(); // 停止定时器 + RespiratoryTrainingModel::GetInstance().AddRespiratoryTrainingTimes(); // 呼吸训练次数加1 + p_RespiratoryTrainingView->GetRespiratoryTrainingAnimator_()->Stop(); // 关闭呼吸动画 +#ifdef FD230_650 + HeartModel::GetInstance()->Heart_Control(HeartState::End, HeartCheck::INITIATIVE); // 关闭心率检测 +#endif + p_RespiratoryTrainingView->ChangeView(RESPIRATORYTRAINING, RESPIRATORYTRAININGCOMPLETED); + ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); /*取消常亮屏*/ + return; + } + + /* + * @brief 回调函数 + */ + static void RT_TimerCallback(int data) + { + GraphicService::GetInstance()->PostGraphicEvent(std::bind(RT_TimerCallbackProc, data)); + } + + /* + * @brief 开启定时器函数 + * @param interval 时间间隔,单位ms + */ + void RespiratoryTrainingModel::RT_StartTimer(uint64_t interval) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingModel::RT_StartTimer"); + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_timer != NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!"); + return; + } + + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_timer = osTimerNew((osTimerFunc_t)RT_TimerCallback, osTimerPeriodic, NULL, NULL); + // 检查定时器创建是否成功 + if (g_timer == NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!"); + return; + } + + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + + /* --------------------------------- 4.启动定时器 -------------------------------- */ + osStatus_t ret = osTimerStart(g_timer, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 NULL -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + if (g_timer != NULL) + { + ret = osTimerDelete(g_timer); + } + g_timer = NULL; + return; + } + } + + /* + * @brief 停止定时器 + */ + void RespiratoryTrainingModel::RT_StopTimer(void) + { + // 检查定时器是否存在 + if (g_timer != NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingModel::RT_StopTimer"); + osTimerStop(g_timer); + // 删除定时器并置为 NULL + osStatus_t ret = osTimerDelete(g_timer); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + } + g_timer = NULL; + } + } +} diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingPresenter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingPresenter.cpp new file mode 100644 index 000000000..26ba3227b --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingPresenter.cpp @@ -0,0 +1,205 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-05-07 11:26:06 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-11-05 14:52:23 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/RespiratoryTraining/src/RespiratoryTrainingPresenter.cpp + */ + +#include "AppViewIDs.h" +#include "NativeAbility.h" +#include "respiratorytraining/include/RespiratoryTrainingPresenter.h" +#include "respiratorytraining/include/RespiratoryTrainingView.h" +#include "common/key_code.h" +#include +#include "UiConfig.h" +#include +#include +#include "respiratorytraining/include/RespiratoryTrainingModel.h" +#include "gfx_utils/mem_check.h" +#include "map" +#include "ui_resource_string.h" +#include "NativeRegisterManager.h" +namespace OHOS +{ + REGIST_MENU_PRO(VIEW_RESPIRATORY_TRAINING, RespiratoryTrainingView, RespiratoryTrainingPresenter, + PNG_APPLIST_BREATHE_IMAGE_BIG, PNG_APPLIST_BREATHE_IMAGE, PNG_APPLIST_BREATHE_IMAGE, "呼吸训练", STR_BREATH_TRAINING); + + // 当前Presenter属性实例化的内存指针 + static RespiratoryTrainingPresenter *g_pRespiratoryTrainingPresenter = nullptr; + + RespiratoryTrainingPresenter::RespiratoryTrainingPresenter() + { + g_pRespiratoryTrainingPresenter = this; +#ifdef MEM_CHECK + MemCheck::GetInstance()->EnableLeakCheck(true); +#endif + } + + RespiratoryTrainingPresenter::~RespiratoryTrainingPresenter() + { + g_pRespiratoryTrainingPresenter = nullptr; +#ifdef MEM_CHECK + MemCheck::GetInstance()->EnableLeakCheck(false); +#endif + } + + RespiratoryTrainingPresenter *RespiratoryTrainingPresenter::GetInstance() + { + return g_pRespiratoryTrainingPresenter; + } + + void RespiratoryTrainingPresenter::OnStart() + { + // ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); + } + + void RespiratoryTrainingPresenter::OnPause(void) + { + Presenter::OnPause(); + } + + void RespiratoryTrainingPresenter::OnResume(void) + { + Presenter::OnResume(); + } + + void RespiratoryTrainingPresenter::OnStop(void) + { + ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); + RespiratoryTrainingModel::GetInstance().RT_StopTimer(); + RespiratoryTrainingModel::GetInstance().ResumeStatus(); + } + + bool RespiratoryTrainingPresenter::OnClick(UIView &view, const ClickEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingPresenter::OnClick"); + std::string viewId = view.GetViewId(); + if (viewId == RTCLABELBUTTON) + { + NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS); + return true; + } + std::map viewMap = { + {TRAINING_DURATION_ONE_MIN, 1}, + {TRAINING_DURATION_TWO_MIN, 2}, + {TRAINING_DURATION_THREE_MIN, 3}, + {TRAINING_DURATION_FOUR_MIN, 4}, + {TRAINING_DURATION_FIVE_MIN, 5}, + }; + auto it = viewMap.find(viewId); + if (it != viewMap.end()) + { + if (viewId == it->first) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "select time = %d", it->second); + RespiratoryTrainingModel::GetInstance().SetRespiratoryTrainingSelectTime(it->second); + if (RespiratoryTrainingDurationSelectionView::GetInstance()) + { + RespiratoryTrainingDurationSelectionView::GetInstance()->UpdateRespiratoryTrainingDurationSelectionView(); + } + } + } + return true; + } + + bool RespiratoryTrainingPresenter::OnDrag(UIView &view, const DragEvent &event) + { + UNUSED(view); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingPresenter::OnDrag"); + if ((event.GetDeltaX() > X_DRAG_OFFSET) && (event.GetDeltaX() > (DOUBLES * MATH_ABS(event.GetDeltaY())))) // 拖动过程中判断是否是水平滑动 + { + RespiratoryTrainingPresenter::X_DRAG_FLAG = true; + } + return true; + } + + bool RespiratoryTrainingPresenter::OnDragEnd(UIView &view, const DragEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingPresenter::OnDragEnd"); + if (event.GetDragDirection() == DragEvent::DIRECTION_LEFT_TO_RIGHT && RespiratoryTrainingPresenter::X_DRAG_FLAG) + { + std::string viewId = view.GetViewId(); + if (viewId == RESPIRATORYTRAINING_DURATIONSELECTION_VIEW) + { + view_->ChangeView(RESPIRATORY_TRAINING_DURATION_SELECTION, RESPIRATORYTRAINING); + } + else + { + NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS); + } + RespiratoryTrainingPresenter::X_DRAG_FLAG = false; + } + return true; + } + + bool RespiratoryTrainingPresenter::OnKeyAct(UIView &view, const KeyEvent &event) // 增加按键事件 + { + UNUSED(view); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingPresenter::OnKeyAct"); + uint16_t keyID = event.GetKeyId(); + uint16_t keyState = event.GetState(); + // 如果是power键,且是亮屏状态,按键释放就返回上一级 + if (keyID == static_cast(ZliteKeyCode::ZLITE_KEY_POWER) && keyState == 1 && uapi_get_screen_state() == 0) + { + NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS); + } + return true; + } + + int RespiratoryTrainingPresenter::GetRespiratoryTrainingSelectTime() + { + int time = RespiratoryTrainingModel::GetInstance().GetRespiratoryTrainingSelectTime(); + int textId; + switch (time) + { + case 1: + textId = STR_ONE_MIN; + break; + case 2: + textId = STR_TWO_MIN; + break; + case 3: + textId = STR_THREE_MIN; + break; + case 4: + textId = STR_FOUR_MIN; + break; + case 5: + textId = STR_FIVE_MIN; + break; + default: + textId = STR_TWO_MIN; + break; + } + return textId; + } + + std::string RespiratoryTrainingPresenter::GetRespiratoryTrainingSelectTime1() + { + int time = RespiratoryTrainingModel::GetInstance().GetRespiratoryTrainingSelectTime(); + std::string text; + switch (time) + { + case 1: + text = "1min"; + break; + case 2: + text = "2min"; + break; + case 3: + text = "3min"; + break; + case 4: + text = "4min"; + break; + case 5: + text = "5min"; + break; + default: + text = "1min"; + break; + } + return text; + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingView.cpp new file mode 100644 index 000000000..f3acf6be6 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/respiratorytraining/src/RespiratoryTrainingView.cpp @@ -0,0 +1,577 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-05-07 11:25:58 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2025-02-24 17:34:43 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/RespiratoryTraining/src/RespiratoryTrainingView.cpp + */ + +#include "respiratorytraining/include/RespiratoryTrainingPresenter.h" +#include "respiratorytraining/include/RespiratoryTrainingView.h" +#include "wearable_log.h" +#include "common/image_cache_manager.h" +#include "animator/easing_equation.h" +#include "ui_resource_string.h" +#include "respiratorytraining/include/RespiratoryTrainingModel.h" +#include "heartrate/include/HeartModel.h" + +#include +#include + +#include "vibrator_service.h" + +namespace OHOS +{ + + static constexpr uint16_t ONE_MIN = 60000; // 1分钟 + static RespiratoryTrainingView *g_pRespiratoryTrainingView{nullptr}; + + RespiratoryTrainingView::RespiratoryTrainingView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::RespiratoryTrainingView"); + g_pRespiratoryTrainingView = this; + } + + RespiratoryTrainingView::~RespiratoryTrainingView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::~RespiratoryTrainingView"); + ClearAll(); + g_pRespiratoryTrainingView = nullptr; + } + + RespiratoryTrainingView *RespiratoryTrainingView::GetInstance() + { + return g_pRespiratoryTrainingView; + } + + bool RespiratoryTrainingView::ChangeRespiratoryTrainingView(int16_t thisView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::ChangeRespiratoryTrainingView"); + if (RespiratoryTrainingScrollView[thisView] == nullptr) + { + AddViewToRootContainer(RespiratoryTrainingScrollView[thisView]); + } + if (TrainingDurationSelectiontitlelabel) + { + TrainingDurationSelectiontitlelabel->SetTextId(presenter_->GetRespiratoryTrainingSelectTime()); + TrainingDurationSelectiontitlelabel->ForceResetText(); + } + return true; + } + + bool RespiratoryTrainingView::ChangeRespiratoryTrainingCompletedView(int16_t thisView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::ChangeRespiratoryTrainingCompletedView"); + if (RespiratoryTrainingScrollView[thisView] == nullptr) + { + p_RespiratoryTrainingCompletedView = new RespiratoryTrainingCompletedView(); + if (p_RespiratoryTrainingCompletedView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new scrollView[%d] fail", thisView); + return false; + } + UIScrollView *scrollView = p_RespiratoryTrainingCompletedView->RespiratoryTrainingCompletedViewInit(); + if (scrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedViewInit fail!!"); + return false; + } + RespiratoryTrainingScrollView[thisView] = scrollView; + AddViewToRootContainer(RespiratoryTrainingScrollView[thisView]); + } + return true; + } + + bool RespiratoryTrainingView::ChangeRespiratoryTrainingDurationSelectionView(int16_t thisView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::ChangeRespiratoryTrainingCompletedView"); + if (RespiratoryTrainingScrollView[thisView] == nullptr) + { + p_RespiratoryTrainingDurationSelectionView = new RespiratoryTrainingDurationSelectionView(); + if (p_RespiratoryTrainingDurationSelectionView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new scrollView[%d] fail", thisView); + return false; + } + UIScrollView *scrollView = p_RespiratoryTrainingDurationSelectionView->RespiratoryTrainingDurationSelectionViewInit(); + if (scrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingDurationSelectionViewInit fail!!"); + return false; + } + RespiratoryTrainingScrollView[thisView] = scrollView; + AddViewToRootContainer(RespiratoryTrainingScrollView[thisView]); + } + return true; + } + + struct RespiratoryTrainingViewMapper + { + const int16_t viewId; + bool (RespiratoryTrainingView::*func)(int16_t thisView); + }; + + static const RespiratoryTrainingViewMapper ViewMapper[] = { + {RESPIRATORYTRAINING, &RespiratoryTrainingView::ChangeRespiratoryTrainingView}, + {RESPIRATORYTRAININGCOMPLETED, &RespiratoryTrainingView::ChangeRespiratoryTrainingCompletedView}, + {RESPIRATORY_TRAINING_DURATION_SELECTION, &RespiratoryTrainingView::ChangeRespiratoryTrainingDurationSelectionView}, + }; + + bool RespiratoryTrainingView::ClickFunc(int16_t interface) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::ClickFunc"); + int funcSize = sizeof(ViewMapper) / sizeof(ViewMapper[0]); + for (int i = 0; i < funcSize; i++) + { + if (interface == ViewMapper[i].viewId) + { + bool jug = (this->*(ViewMapper[i].func))(interface); + if (jug == false) + { + return false; + } + return true; + } + } + return false; + } + + void RespiratoryTrainingView::ChangeView(int16_t hideView, int16_t showView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::ChangeView"); + if (hideView > MAX_RESPIRATORYTRAININGID) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Overstep ones bounds"); + return; + } + RespiratoryTrainingScrollView[hideView]->SetVisible(false); + ClickFunc(showView); + RespiratoryTrainingScrollView[showView]->SetVisible(true); + Draw(); + } + + Animator *RespiratoryTrainingView::GetRespiratoryTrainingAnimator_() + { + if (RespiratoryTrainingAnimator_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingAnimator_ is nullptr!!"); + return nullptr; + } + return RespiratoryTrainingAnimator_; + } + + const static int16_t BUTTON_WIDTH = 320; + const static int16_t BUTTON_HEIGHT = 100; + const static int16_t INTERVAL_STEP = 80; + const Vector2 VIEW_CENTER = {120, 120}; + static constexpr const char *RespiratoryTrainingImagePath = "/user/res/RespiratoryTraining/RespiratoryTraining.bin"; + static constexpr const char *RespiratoryTrainingImageBGPath = "/user/res/RespiratoryTraining/RespiratoryTraining_BG.bin"; + + void RespiratoryTrainingCallback::Callback(UIView *view) + { + RespiratoryTrainingModel::GetInstance().calculateHeartrateTotal(); + // 1.计算当前时间与开始时间的差值,用于控制动画的时间。 + uint32_t currentTime = HALTick::GetInstance().GetTime(); + curTime = currentTime - startTimestamp; + + // 2.判断当前时间是否大于等于训练总时长,若是则进行下一步操作。 + if (curTime >= durationTime) + { + prepare_count++; + // 计算动画缩放比例 + scale = static_cast(EasingEquation::QuadEaseInOut(startVal, endVal, durationTime, durationTime)) / durationTime; + + // 切换起始值和结束值,更新下一次呼吸的状态。 + std::swap(startVal, endVal); + startTimestamp = currentTime; + + if (prepare_count >= 2) + { + // 只有在准备时间结束后才切换呼吸状态和文本 + isBreathIn = !isBreathIn; + if (isBreathIn) + { + // breath->SetText("现在吸气"); + breath->SetTextId(STR_INHALE_NOW); + } + else + { + // breath->SetText("现在呼气"); + breath->SetTextId(STR_EXHALE_NOW); + } + // 震动提醒 + ui_api_vibrate_once_func(); + breath->ForceResetText(); + } + } + else + { + // 继续进行呼吸动画的变化 + scale = static_cast(EasingEquation::QuadEaseInOut(startVal, endVal, curTime, durationTime)) / durationTime; + } + + // 根据动画步长 step 更新图片的旋转角度 angle + angle += step; + if (angle <= -360) + { + angle = 0; + } + + // 根据计算得到的缩放比例 scale 对图片进行缩放操作,并根据角度对图片进行旋转操作 + img_->Scale({scale, scale}, VIEW_CENTER); + img_->Rotate(angle, VIEW_CENTER); + img_->Invalidate(); + } + + void RespiratoryTrainingView::HandStartRespiratoryTraining() + { + if (titlelabel && TrainingDurationSelectiontitlelabel && Image && RespiratoryTrainingStartButton && RespiratoryTrainingStartLabel) + { + titlelabel->SetVisible(false); + TrainingDurationSelectiontitlelabel->SetVisible(false); + Image->SetVisible(false); + RespiratoryTrainingStartButton->SetVisible(false); + RespiratoryTrainingStartLabel->SetVisible(false); + } + + if (RespiratoryTrainingStartNote_ && RespiratoryTrainingImg_) + { + RespiratoryTrainingStartNote_->SetVisible(true); + RespiratoryTrainingImg_->SetVisible(true); + } + ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); // 开始训练后常亮屏 + uapi_dev_runtime_set_respiratory_training_status(1); // 训练开始runtime设置为1 + StartRespiratoryTraining(); // 开始呼吸训练 +#ifdef FD230_650 + HeartModel::GetInstance()->Heart_Control(HeartState::Start, HeartCheck::INITIATIVE); // 开启心率检测 +#endif + RespiratoryTrainingModel::GetInstance().RT_StartTimer(RespiratoryTrainingModel::GetInstance().GetRespiratoryTrainingTime()); // 开启定时器 + ui_api_vibrate_once_func(); // 震动 + } + + bool RespiratoryTrainingView::OnClick(UIView &view, const ClickEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::OnClick"); + UNUSED(event); + + if (&view == RespiratoryTrainingStartButton) + { + HandStartRespiratoryTraining(); + } + else if (&view == TrainingDurationSelectiontitlelabel) + { + ChangeView(RESPIRATORYTRAINING, RESPIRATORY_TRAINING_DURATION_SELECTION); + } + return true; + } + + // 开始呼吸训练 + bool RespiratoryTrainingView::StartRespiratoryTraining() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::StartRespiratoryTraining"); + if (!animateStart_) + { + RespiratoryTrainingAnimator_->Start(); + animateStart_ = true; + if (RespiratoryTrainingStartNote_ != nullptr) + { + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Remove(RespiratoryTrainingStartNote_); + delete RespiratoryTrainingStartNote_; + RespiratoryTrainingStartNote_ = nullptr; + } + RespiratoryTrainingLabel_ = new UILabelExt(); + if (RespiratoryTrainingLabel_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingLabel_ new fail"); + return false; + } + RespiratoryTrainingLabel_->SetPosition(53, 320, 360, 70); + RespiratoryTrainingLabel_->SetTextId(STR_KEEP_STILL_FOCUS_ON_BREATHING); // 准备 + RespiratoryTrainingLabel_->SetStyle(STYLE_TEXT_FONT, 30); + RespiratoryTrainingLabel_->SetStyle(STYLE_LINE_HEIGHT, 35); + RespiratoryTrainingLabel_->SetLineBreakMode(UILabel::LINE_BREAK_WRAP); + RespiratoryTrainingLabel_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + RespiratoryTrainingLabel_->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + RespiratoryTrainingLabel_->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(RespiratoryTrainingLabel_); + RespiratoryTrainingCallBack_->SetTextView(RespiratoryTrainingLabel_); + RespiratoryTrainingCallBack_->startTimestamp = HALTick::GetInstance().GetTime(); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Invalidate(); + } + return true; + } + + bool RespiratoryTrainingView::InitRespiratoryTrainingElements() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::InitRespiratoryTrainingElements"); + // 加载呼吸训练图片 + ImageInfo *imgInfo = ImageCacheManager::GetInstance().LoadSingleRes(RespiratoryTrainingImagePath); + if (imgInfo == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Load image failed!"); + return false; + } + + // 创建并设置呼吸训练图片 + RespiratoryTrainingImg_ = new UIImageView(); + if (RespiratoryTrainingImg_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingImg_ new failed!"); + return false; + } + RespiratoryTrainingImg_->SetSrc(imgInfo); + RespiratoryTrainingImg_->SetPosition(113, 70, 240, 240); + RespiratoryTrainingImg_->SetStyle(STYLE_IMAGE_OPA, OPA_OPAQUE); + RespiratoryTrainingImg_->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); + RespiratoryTrainingImg_->SetAutoEnable(false); + RespiratoryTrainingImg_->SetResizeMode(UIImageView::ImageResizeMode::CENTER); + RespiratoryTrainingImg_->SetVisible(false); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(RespiratoryTrainingImg_); + /* -------------------------------------------------------------------------- */ + RespiratoryTrainingStartNote_ = new UILabelExt(); + if (RespiratoryTrainingStartNote_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingStartNote_ new failed!"); + return false; + } + RespiratoryTrainingStartNote_->SetPosition(53, 320, 360, 70); + RespiratoryTrainingStartNote_->SetStyle(STYLE_TEXT_FONT, 30); + RespiratoryTrainingStartNote_->SetStyle(STYLE_LINE_HEIGHT, 35); + // RespiratoryTrainingStartNote_->SetText("保持不动,将注意力集中在呼吸上"); + RespiratoryTrainingStartNote_->SetTextId(STR_KEEP_STILL_FOCUS_ON_BREATHING); + RespiratoryTrainingStartNote_->SetLineBreakMode(UILabel::LINE_BREAK_WRAP); + RespiratoryTrainingStartNote_->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + RespiratoryTrainingStartNote_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + RespiratoryTrainingStartNote_->SetVisible(false); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(RespiratoryTrainingStartNote_); + return true; + } + + bool RespiratoryTrainingView::InitRespiratoryTrainingElements2() + { + titlelabel = new UILabelExt(); + if (titlelabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "titlelabel new failed!"); + return false; + } + titlelabel->SetPosition(83, 50, 300, 35); + titlelabel->SetStyle(STYLE_TEXT_FONT, 30); + titlelabel->SetStyle(STYLE_LINE_HEIGHT, 35); + titlelabel->SetTextId(STR_BREATH_TRAINING); + titlelabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + titlelabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + titlelabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(titlelabel); + /* -------------------------------------------------------------------------- */ + TrainingDurationSelectiontitlelabel = new UILabelExt(); + if (TrainingDurationSelectiontitlelabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TrainingDurationSelectiontitlelabel new failed!"); + return false; + } + TrainingDurationSelectiontitlelabel->SetPosition(83, 95, 300, 35); + TrainingDurationSelectiontitlelabel->SetStyle(STYLE_TEXT_FONT, 30); + TrainingDurationSelectiontitlelabel->SetStyle(STYLE_LINE_HEIGHT, 35); + TrainingDurationSelectiontitlelabel->SetTextId(presenter_->GetRespiratoryTrainingSelectTime()); + TrainingDurationSelectiontitlelabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + TrainingDurationSelectiontitlelabel->SetTextColor(Color::GetColorFromRGBA(0x66, 0x66, 0x66, 0xff)); + TrainingDurationSelectiontitlelabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + TrainingDurationSelectiontitlelabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + TrainingDurationSelectiontitlelabel->SetTouchable(true); + TrainingDurationSelectiontitlelabel->SetOnClickListener(this); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(TrainingDurationSelectiontitlelabel); + /* -------------------------------------------------------------------------- */ + Image = new UIImageView(); + if (Image == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Image new failed!"); + return false; + } + Image->SetSrc(RespiratoryTrainingImageBGPath); + Image->SetPosition(133, 133, 200, 200); + Image->SetStyle(STYLE_IMAGE_OPA, OPA_OPAQUE); + Image->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT); + Image->SetAutoEnable(false); + Image->SetResizeMode(UIImageView::CENTER); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(Image); + /* -------------------------------------------------------------------------- */ + RespiratoryTrainingStartButton = new UILabelButtonExt(); + if (RespiratoryTrainingStartButton == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Image new failed!"); + return false; + } + RespiratoryTrainingStartButton->SetPosition(93, 330, 280, 90); + RespiratoryTrainingStartButton->SetOnClickListener(this); + RespiratoryTrainingStartButton->SetStyle(STYLE_BACKGROUND_COLOR, 0xff4fc34c); + RespiratoryTrainingStartButton->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + RespiratoryTrainingStartButton->SetStyleForState(STYLE_BACKGROUND_OPA, 0x00, UIButton::PRESSED); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(RespiratoryTrainingStartButton); + /* -------------------------------------------------------------------------- */ + RespiratoryTrainingStartLabel = new UILabelExt(); + if (RespiratoryTrainingStartLabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingStartLabel new failed!"); + return false; + } + RespiratoryTrainingStartLabel->SetPosition(143, 358, 180, 35); + RespiratoryTrainingStartLabel->SetStyle(STYLE_TEXT_FONT, 30); + RespiratoryTrainingStartLabel->SetStyle(STYLE_LINE_HEIGHT, 35); + RespiratoryTrainingStartLabel->SetTextId(STR_START); // 开始 + RespiratoryTrainingStartLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + RespiratoryTrainingStartLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + RespiratoryTrainingStartLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->Add(RespiratoryTrainingStartLabel); + return true; + } + + bool RespiratoryTrainingView::InitRespiratoryTrainingCallBackAndAnimator() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::InitRespiratoryTrainingCallBackAndAnimator"); + RespiratoryTrainingCallBack_ = new RespiratoryTrainingCallback(RespiratoryTrainingImg_); + if (RespiratoryTrainingCallBack_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "callBack new fail"); + return false; + } + + RespiratoryTrainingAnimator_ = new Animator(RespiratoryTrainingCallBack_, RespiratoryTrainingImg_, 0, true); + if (RespiratoryTrainingAnimator_ == nullptr) + { + delete RespiratoryTrainingCallBack_; + RespiratoryTrainingCallBack_ = nullptr; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Animator new fail"); + return false; + } + + animateStart_ = false; + + return true; + } + + bool RespiratoryTrainingView::InitRespiratoryTrainingScrollView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingCompletedView::CreateRespiratoryTrainingCompletedScrollView"); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING] = new UIScrollView(); + if (RespiratoryTrainingScrollView[RESPIRATORYTRAINING] == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScrollView new fail!"); + return false; + } + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight()); + // RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->SetScrollBlankSize(50); + // RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->SetReboundSize(35); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->SetHorizontalScrollState(false); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->SetTouchable(true); + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->SetDraggable(true); + AddViewToRootContainer(RespiratoryTrainingScrollView[RESPIRATORYTRAINING]); + + return true; + } + + void RespiratoryTrainingView::RespiratoryTrainingViewInit(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RespiratoryTrainingView::RespiratoryTrainingViewInit"); + if (!InitRespiratoryTrainingScrollView() || !InitRespiratoryTrainingElements() || + !InitRespiratoryTrainingElements2() || !InitRespiratoryTrainingCallBackAndAnimator()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "RecordListViewInit fail!!"); + return; + } +#if 0 + StartRespiratoryTraining(); // 开始呼吸训练 + HeartModel::GetInstance()->Heart_Control(HeartState::Start, HeartCheck::INITIATIVE); // 开启心率检测 + RespiratoryTrainingModel::GetInstance().RT_StartTimer(ONE_MIN); // 开启一个一分钟的定时器 + ui_api_vibrate_once_func(); // 震动提醒 +#endif + } + + void RespiratoryTrainingView::ClearAll(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[RespiratoryTrainingView]ClearAll start"); + if (RespiratoryTrainingScrollView[RESPIRATORYTRAINING] != nullptr) + { + RespiratoryTrainingScrollView[RESPIRATORYTRAINING]->RemoveAll(); + delete RespiratoryTrainingScrollView[RESPIRATORYTRAINING]; + RespiratoryTrainingScrollView[RESPIRATORYTRAINING] = nullptr; + } + + if (RespiratoryTrainingAnimator_ != nullptr) + { + RespiratoryTrainingAnimator_->Stop(); + delete RespiratoryTrainingAnimator_; + RespiratoryTrainingAnimator_ = nullptr; + } + + if (RespiratoryTrainingCallBack_ != nullptr) + { + delete RespiratoryTrainingCallBack_; + RespiratoryTrainingCallBack_ = nullptr; + } + + if (RespiratoryTrainingImg_ != nullptr) + { + ImageCacheManager::GetInstance().UnloadSingleRes(RespiratoryTrainingImagePath); + delete RespiratoryTrainingImg_; + RespiratoryTrainingImg_ = nullptr; + } + + if (RespiratoryTrainingLabel_ != nullptr) + { + delete RespiratoryTrainingLabel_; + RespiratoryTrainingLabel_ = nullptr; + } + if (RespiratoryTrainingStartNote_ != nullptr) + { + delete RespiratoryTrainingStartNote_; + RespiratoryTrainingStartNote_ = nullptr; + } + if (titlelabel != nullptr) + { + delete titlelabel; + titlelabel = nullptr; + } + if (TrainingDurationSelectiontitlelabel != nullptr) + { + delete TrainingDurationSelectiontitlelabel; + TrainingDurationSelectiontitlelabel = nullptr; + } + if (Image != nullptr) + { + delete Image; + Image = nullptr; + } + if (RespiratoryTrainingStartButton != nullptr) + { + delete RespiratoryTrainingStartButton; + RespiratoryTrainingStartButton = nullptr; + } + if (RespiratoryTrainingStartLabel != nullptr) + { + delete RespiratoryTrainingStartLabel; + RespiratoryTrainingStartLabel = nullptr; + } + + if (p_RespiratoryTrainingCompletedView != nullptr) + { + delete p_RespiratoryTrainingCompletedView; + p_RespiratoryTrainingCompletedView = nullptr; + RespiratoryTrainingScrollView[RESPIRATORYTRAININGCOMPLETED] = nullptr; + } + + if (p_RespiratoryTrainingDurationSelectionView != nullptr) + { + delete p_RespiratoryTrainingDurationSelectionView; + p_RespiratoryTrainingDurationSelectionView = nullptr; + RespiratoryTrainingScrollView[RESPIRATORY_TRAINING_DURATION_SELECTION] = nullptr; + } + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[RespiratoryTrainingView]ClearAll end!!"); + } + + void RespiratoryTrainingView::OnStart() + { + RespiratoryTrainingViewInit(); + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchPresenter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchPresenter.h new file mode 100644 index 000000000..1152b15bd --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchPresenter.h @@ -0,0 +1,77 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-04-04 15:13:51 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-10-30 14:51:08 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/include/MainStopWatchPresenter.h + */ +#ifndef MAIN_STOPWATCH_PRESENTER_H +#define MAIN_STOPWATCH_PRESENTER_H + +#include "Presenter.h" +#include "View.h" +#include "MainStopWatchView.h" +#include +#include "ui_resource_string.h" +#include "ModelListenerSample.h" +/*秒表主视图*/ +namespace OHOS +{ + static constexpr int STOPWATCH_TIMER_DURATION = 10; // 定时器周期,每10毫秒定时器会触发一次 + static constexpr int MAX_RECORD_LOOPS = 99; // 最大记录圈数为99 + static const char *MAX_RECORD_TIME = "99:59.99"; // 最高记录时间为99:59.99 + typedef enum + { + MAIN_STOPWATCH = 0, // 秒表主视图 + STOPWATCH_RECORD_CYCLE_TO_LIMIT, // 到达秒表计时的最高记录圈数后弹出视图 + STOPWATCH_RECORD_TIME_TO_LIMIT, // 到达秒表最大的记录时间后弹出该视图 + STOPWATCH_MAXVIEWID, // 秒表的视图id数量 + } StopWatchViewId; + class MainStopWatchView; + class MainStopWatchPresenter : public Presenter, + public UIView::OnClickListener, + public UIView::OnDragListener, + public RootView::OnKeyActListener, + public UICheckBox::OnChangeListener, + public ModelListenerSample + { + public: + MainStopWatchPresenter(); + virtual ~MainStopWatchPresenter(); + void OnStart() override; + void OnPause() override; + void OnResume() override; + void OnStop() override; + static MainStopWatchPresenter *GetInstance(); + void SetCheckBoxAndButton(UICheckBox *checkbox, UIButton *button); + void SetLable(UILabel *label1, UILabel *label2); + void SetShowTimeLableStyle(UILabel *label, int x, int y, int TextFont, int LineHeight); + void SetList(UIList *list, TextAdapter *listadapter, List *listdata); + void SetImage(UIImageView *image); + + private: + // 因为继承了OnClickListener,所以有OnClick属性,至于参数,原函数也这样直接继承; + bool OnClick(UIView &view, const ClickEvent &event) override; + bool OnDrag(UIView &view, const DragEvent &event) override; + bool OnDragEnd(UIView &view, const DragEvent &event) override; + bool OnChange(UICheckBox::UICheckBoxState state) override; + bool OnKeyAct(UIView &view, const KeyEvent &event) override; // 增加按键事件 + void Notify() override; + private: + UICheckBox *m_checkbox{nullptr}; + UIButton *m_button{nullptr}; + UILabel *m_stopWatchlabel{nullptr}; + UILabel *m_showTimelabel{nullptr}; + UIImageView *m_image{nullptr}; + UIList *m_list = nullptr; + TextAdapter *m_listadapter = nullptr; + List *m_listdata = nullptr; + uint64_t lastRecordTime = 0; // 上次记录时间 + int RecordCycleNumber{0}; // 用来记录计时圈数 + bool X_DRAG_FLAG{false}; + bool isStartMark{false}; + bool TimerIsRunning{false}; + }; +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchView.h new file mode 100644 index 000000000..ffbaadbd7 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/MainStopWatchView.h @@ -0,0 +1,82 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-04-04 15:13:51 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2025-02-24 17:21:50 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/include/MainStopWatchView.h + */ +#ifndef MAIN_STOPWATCH_VIEW_H +#define MAIN_STOPWATCH_VIEW_H + + +#include "View.h" +#include "components/ui_view_group.h" +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_checkbox.h" +#include "components/ui_button.h" +#include "components/ui_list.h" +#include "components/text_adapter.h" +#include "stopwatch/include/StopWatchRecordCycleToLimitView.h" +#include "stopwatch/include/StopWatchRecordTimeToLimitView.h" +#include "stopwatch/include/StopWatchAdapter.h" +/*秒表主视图*/ +namespace OHOS +{ + + static const char *checkBox1selectedImg = "/user/res/countdown/COUNTDOWM_PLAY.bin"; // 播放 + static const char *checkBox1unSelectedImg = "/user/res/countdown/COUNTDOWM_PAUSE.bin"; // 暂停 + static const char *ResetOrMarkButtonImg_Reset1 = "/user/res/stopwatch/STOPWATH_RESET1.bin"; // 重置_灰色 图片 + static const char *ResetOrMarkButtonImg_Reset2 = "/user/res/stopwatch/STOPWATH_RESET2.bin"; // 重置_白色 图片 + static const char *ResetOrMarkButtonImg_Mark = "/user/res/stopwatch/STOPWATCH_MARK.bin"; // 标记 图片 + static const char *PlayOrPausecheckBoxVIEWID = "PlayOrPausecheckBox"; // 播放或暂停复选框视图ID + static const char *ResetOrMarkButton_RESET1_VIEWID = "ResetOrMarkButtonReset1"; // ResetOrMarkButtonReset1 + static const char *ResetOrMarkButton_RESET2_VIEWID = "ResetOrMarkButtonReset2"; // ResetOrMarkButtonReset2 + static const char *ResetOrMarkButton_MARK_VIEWID = "ResetOrMarkButtonMark"; // ResetOrMarkButtonMark + static const char *CycleToLimitReturnButton_VIEWID = "CycleToLimitReturnButton"; // CycleToLimitReturnButton + static const char *TimeToLimitReturnButton_VIEWID = "TimeToLimitReturnButton"; // TimeToLimitReturnButton + class MainStopWatchPresenter; + class MainStopWatchView : public View + { + + public: + MainStopWatchView(); + virtual ~MainStopWatchView(); + static MainStopWatchView *GetInstance(void); + + void OnStart() override; + void SetViewIsVisible(UIView *view, bool status); + bool ClickFunc(int16_t interface); + void ChangeView(int16_t hideView, int16_t showView); + bool ChangeMainStopWatch(int16_t thisView); + bool ChangeStopWatchRecordCycleLimit(int16_t thisView); + bool ChangeMainStopWatchRecordTimeLimit(int16_t thisView); + UILabelExt *GetShowTimelabel(void); + UICheckBox *GetPlayOrPausecheckBox(void); + void ChangeRecordTimeToLimitView(void); + UIScrollView *GetScrollView(int16_t index); + StopWatchAdapter *GetStopWatchAdapter(void); + private: + void InitMainStopWatchView(void); + void ClearAll(void); + + private: + StopWatchRecordCycleToLimitView *p_StopWatchRecordCycleToLimitView{nullptr}; // 圈数到达上限后弹出该视图 + StopWatchRecordTimeToLimitView *p_StopWatchRecordTimeToLimitView{nullptr}; // 计时时间到达上限后弹出该视图 + + private: + UIViewGroup *group = nullptr; + UIScrollView *scrollView[3] = {nullptr}; + UILabelExt *stopWatchlabel = nullptr; // 内容为“秒表”的标签 + UILabelExt *showTimelabel = nullptr; // 用来显示计时时间 + UICheckBox *PlayOrPausecheckBox = nullptr; // 播放或暂停复选框 + UIButton *ResetOrMarkbutton = nullptr; // 重置或标记按钮 + UIImageView *LineImage{nullptr}; + UIList *list = nullptr; + TextAdapter *listadapter = nullptr; + List *listdata = nullptr; + + StopWatchAdapter *stopWatchAdapter{nullptr}; + }; +} // namespace OHOS +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchAdapter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchAdapter.h new file mode 100644 index 000000000..8720b6901 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchAdapter.h @@ -0,0 +1,47 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-12-12 11:03:15 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-12-16 11:43:14 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/include/StopWatchAdapter.h + */ + +#ifndef STOPWATCH_ADAPTER_H +#define STOPWATCH_ADAPTER_H + +#include "components/ui_list.h" +#include "components/ui_label.h" +#include "components/ui_label_ext.h" +#include "components/ui_view_group.h" +#include "components/ui_image_view.h" +#include "components/abstract_adapter.h" +#include +#include + +namespace OHOS +{ + typedef struct + { + std::string RecordCycleNumber; + std::string formattedTime; + std::string formattedDiff; + int curSelectItemViewIndex; + } StopWatchItem; + + class StopWatchAdapter : public AbstractAdapter + { + public: + explicit StopWatchAdapter(); + ~StopWatchAdapter() override; + uint16_t GetCount(void) override; + void ClearData(void); + void setSelectedIndex(int index); + UIView *GetView(UIView *inView, int16_t index) override; + void AddListItem(const StopWatchItem &item); + + private: + std::list listData; + int curSelectItemViewIndex{-1}; + }; +} +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchItemView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchItemView.h new file mode 100644 index 000000000..9f5f11a60 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchItemView.h @@ -0,0 +1,32 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-03-30 09:14:38 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-12-16 14:42:31 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/settings/include/SettingItemView.h + */ + +#ifndef STOPWATCH_ITEM_VIEW_H +#define STOPWATCH_ITEM_VIEW_H + +#include "components/ui_label_ext.h" +#include "components/ui_view_group.h" +#include "stopwatch/include/StopWatchAdapter.h" +namespace OHOS +{ + class StopWatchItemView : public UIViewGroup + { + public: + explicit StopWatchItemView(); + ~StopWatchItemView() override; + void SetItemInfo(const StopWatchItem itemInfo); + void SetUpChild(); + void SetItemViewColor(bool flag); + + private: + UILabel RecordCycleNumber; + UILabel formattedTime; + UILabel formattedDiff; + }; +} +#endif diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchModel.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchModel.h new file mode 100644 index 000000000..b2d2a770c --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchModel.h @@ -0,0 +1,43 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-04-04 15:13:51 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-11-27 17:45:02 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/include/StopWatchModel.h + */ +#ifndef STOP_WATCH_MODEL_H +#define STOP_WATCH_MODEL_H + +#include +#include +#include + +namespace OHOS +{ + + class StopWatchModel + { + public: + static std::shared_ptr GetInstance(); // shared_ptr:当没有引用指向这个实例时会自动释放内存 + ~StopWatchModel() {} + std::string DisplayStopWatchDuration(); + void StopWatch_StartTimer(uint32_t interval); + void StopWatch_StopTimer(void); + void StopWatch_PauseTimer(); + void StopWatch_ResumeTimer(uint32_t interval); + bool isReachMaxRecordTime(void); + + + private: + // 将构造函数、拷贝构造函数和赋值操作符私有化 + StopWatchModel() = default; + StopWatchModel(const StopWatchModel &) = delete; + StopWatchModel &operator=(const StopWatchModel &) = delete; + + private: + std::string stopwatchDuration; + }; + +} + +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordCycleToLimitView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordCycleToLimitView.h new file mode 100644 index 000000000..85d24ef97 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordCycleToLimitView.h @@ -0,0 +1,39 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-04-04 15:13:51 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-04-07 16:07:11 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/include/StopWatchRecordCycleToLimitView.h + */ +#ifndef STOPWATCH_RECORD_CYCLE_TO_LIMIT_VIEW_H +#define STOPWATCH_RECORD_CYCLE_TO_LIMIT_VIEW_H + + +#include "View.h" +#include "components/ui_view_group.h" +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_image_view.h" +#include "components/ui_label_button_ext.h" +/*弹窗视图:到达最高圈数99时弹出*/ +namespace OHOS +{ + class StopWatchRecordCycleToLimitView + { + + public: + StopWatchRecordCycleToLimitView(); + void ClearAll(void); + virtual ~StopWatchRecordCycleToLimitView(); + static StopWatchRecordCycleToLimitView *GetInstance(void); + UIScrollView *InitStopWatchRecordCycleToLimitView(void); + + private: + UIScrollView *scrollView = nullptr; + UILabelExt *Title = nullptr; + UIImageView *AttentionImage = nullptr; + UILabelExt *AttentionLabel = nullptr; + UILabelButtonExt *button = nullptr; + }; +} // namespace OHOS +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordTimeToLimitView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordTimeToLimitView.h new file mode 100644 index 000000000..d5a62534a --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/include/StopWatchRecordTimeToLimitView.h @@ -0,0 +1,39 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-04-04 15:13:51 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-04-07 16:28:41 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/include/StopWatchRecordTimeToLimitView.h + */ +#ifndef STOPWATCH_RECORD_TIME_TO_LIMIT_VIEW_H +#define STOPWATCH_RECORD_TIME_TO_LIMIT_VIEW_H + + +#include "View.h" +#include "components/ui_view_group.h" +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_image_view.h" +#include "components/ui_label_button_ext.h" +/*弹窗视图:到达最高时间99:59.99时弹出*/ +namespace OHOS +{ + class StopWatchRecordTimeToLimitView + { + public: + StopWatchRecordTimeToLimitView(); + virtual ~StopWatchRecordTimeToLimitView(); + static StopWatchRecordTimeToLimitView *GetInstance(void); + UIScrollView *InitStopWatchRecordTimeToLimitView(void); + void ClearAll(void); + + private: + UIScrollView *scrollView = nullptr; + UILabelExt *Title = nullptr; + UIImageView *AttentionImage = nullptr; + UILabelExt *AttentionLabel_1 = nullptr; + UILabelExt *AttentionLabel_2 = nullptr; + UILabelButtonExt *button = nullptr; + }; +} // namespace OHOS +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchPresenter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchPresenter.cpp new file mode 100644 index 000000000..249a639cb --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchPresenter.cpp @@ -0,0 +1,377 @@ +#include "AppViewIDs.h" +#include "NativeAbility.h" +#include "UiConfig.h" +#include "stopwatch/include/MainStopWatchPresenter.h" +#include "stopwatch/include/StopWatchModel.h" +#include "common/key_code.h" +#include +/*秒表主视图*/ +#include "gfx_utils/mem_check.h" + +#include "NativeRegisterManager.h" +namespace OHOS +{ + REGIST_MENU_PRO(VIEW_MAIN_STOPWATCH, MainStopWatchView, MainStopWatchPresenter, + PNG_APPLIST_STOPWATCH_IMAGE_BIG, PNG_APPLIST_STOPWATCH_IMAGE, PNG_APPLIST_STOPWATCH_IMAGE, "秒表", STR_STOPWATCH); + + // 当前Presenter属性实例化的内存指针 + static MainStopWatchPresenter *g_pMainStopWatchPresenter = nullptr; + + MainStopWatchPresenter::MainStopWatchPresenter() + { + g_pMainStopWatchPresenter = this; +#ifdef MEM_CHECK + MemCheck::GetInstance()->EnableLeakCheck(true); +#endif + } + + MainStopWatchPresenter::~MainStopWatchPresenter() + { + StopWatchModel::GetInstance()->StopWatch_StopTimer(); // 退出删除并清理定时器资源 + g_pMainStopWatchPresenter = nullptr; +#ifdef MEM_CHECK + MemCheck::GetInstance()->EnableLeakCheck(false); +#endif + } + + MainStopWatchPresenter *MainStopWatchPresenter::GetInstance() + { + return g_pMainStopWatchPresenter; + } + + void MainStopWatchPresenter::OnStart() + { + // ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); // 长亮屏 + } + + void MainStopWatchPresenter::OnPause(void) + { + + Presenter::OnPause(); + } + + void MainStopWatchPresenter::OnResume(void) + { + + Presenter::OnResume(); + } + + void MainStopWatchPresenter::OnStop(void) + { + // ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); // 取消长亮屏 + } + + /// @brief 设置复选框和按钮 + /// @param checkbox + /// @param button + void MainStopWatchPresenter::SetCheckBoxAndButton(UICheckBox *checkbox, UIButton *button) + { + m_checkbox = checkbox; + m_button = button; + } + + /// @brief 设置标签 + /// @param label1 + /// @param label2 + void MainStopWatchPresenter::SetLable(UILabel *label1, UILabel *label2) + { + m_stopWatchlabel = label1; + m_showTimelabel = label2; + } + + /// @brief 设置显示时间的标签样式 + /// @param label + /// @param x + /// @param y + /// @param TextFont + /// @param LineHeight + void MainStopWatchPresenter::SetShowTimeLableStyle(UILabel *label, int x, int y, int TextFont, int LineHeight) + { + label->SetPosition(x, y, 466, LineHeight); + label->SetStyle(STYLE_TEXT_FONT, TextFont); + label->SetStyle(STYLE_LINE_HEIGHT, LineHeight); + label->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, TextFont); + label->SetLineBreakMode(UILabel::LINE_BREAK_CLIP); + label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + label->Invalidate(); + } + + void MainStopWatchPresenter::SetList(UIList *list, TextAdapter *listadapter, List *listdata) + { + m_list = list; + m_listadapter = listadapter; + m_listdata = listdata; + } + + void MainStopWatchPresenter::SetImage(UIImageView *image) + { + m_image = image; + } + + bool MainStopWatchPresenter::OnDrag(UIView &view, const DragEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchPresenter::OnDrag"); + UNUSED(view); + if ((event.GetDeltaX() > X_DRAG_OFFSET) && (event.GetDeltaX() > (DOUBLES * MATH_ABS(event.GetDeltaY())))) // 拖动过程中判断是否是水平滑动 + { + MainStopWatchPresenter::X_DRAG_FLAG = true; + } + return true; + } + + bool MainStopWatchPresenter::OnDragEnd(UIView &view, const DragEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchPresenter::OnDragEnd"); + UNUSED(view); + if (event.GetDragDirection() == DragEvent::DIRECTION_LEFT_TO_RIGHT && MainStopWatchPresenter::X_DRAG_FLAG) + { + if (&view == view_->GetScrollView(MAIN_STOPWATCH)) + { + NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS); + } + else if (&view == view_->GetScrollView(STOPWATCH_RECORD_CYCLE_TO_LIMIT)) + { + view_->ChangeView(STOPWATCH_RECORD_CYCLE_TO_LIMIT, MAIN_STOPWATCH); + } + else if (&view == view_->GetScrollView(STOPWATCH_RECORD_TIME_TO_LIMIT)) + { + view_->ChangeView(STOPWATCH_RECORD_TIME_TO_LIMIT, MAIN_STOPWATCH); + } + X_DRAG_FLAG = false; + } + return true; + } + + /* + * Converts a time string in the format "mm:ss.ms" to milliseconds. + * + * @param timeStr The time string to convert. + * @return The time in milliseconds. + */ + static unsigned long TimeStrToMilliseconds(const char *timeStr) + { + unsigned minutes, seconds, milliseconds; + + // Assuming the format is "mm:ss.ms" + if (sscanf(timeStr, "%u:%u.%u", &minutes, &seconds, &milliseconds) == 3) + { + // 将分钟转换为毫秒,将秒转换为毫秒,并将它们相加 + unsigned long totalMilliseconds = (minutes * 60 * 1000) + (seconds * 1000) + (milliseconds * 10); + return totalMilliseconds; + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Invalid time format."); + return 0; + } + } + + /*将毫秒级数转成格式为"mm:ss.ms"*/ + static void MillisecondsToTimeStr(unsigned long milliseconds, char *buffer) + { + unsigned minutes = milliseconds / (60 * 1000); + milliseconds %= (60 * 1000); // Remaining milliseconds after converting to minutes + unsigned seconds = milliseconds / 1000; + unsigned ms = milliseconds % 1000; // Remaining milliseconds after converting to seconds + + // Assuming ms needs to be in hundredths of a second for the ".ms" format + unsigned msHundredths = ms / 10; // Convert to hundredths of a second + + // Write the formatted time string to the buffer + sprintf(buffer, "%02u:%02u.%02u", minutes, seconds, msHundredths); + } + + bool MainStopWatchPresenter::OnClick(UIView &view, const ClickEvent &event) + { + UNUSED(view); + MainStopWatchView *mainStopWatchView = MainStopWatchView::GetInstance(); + const char *clickedViewId = view.GetViewId(); + if (strcmp(clickedViewId, ResetOrMarkButton_MARK_VIEWID) == 0) // 点击标记按钮 + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "RecordCycleNumber:%d\n", RecordCycleNumber); + if (RecordCycleNumber >= MAX_RECORD_LOOPS) // 到达最高记录圈数 + { + m_checkbox->SetState(UICheckBox::UNSELECTED); + mainStopWatchView->ChangeView(MAIN_STOPWATCH, STOPWATCH_RECORD_CYCLE_TO_LIMIT); + return true; + } + else + { + RecordCycleNumber += 1; + } + + if (isStartMark == false) // 第一次标记 + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "isStartMark = %d", isStartMark); + mainStopWatchView->SetViewIsVisible(m_stopWatchlabel, false); + SetShowTimeLableStyle(m_showTimelabel, 0, 60, 65, 78); + mainStopWatchView->SetViewIsVisible(m_list, true); + mainStopWatchView->SetViewIsVisible(m_image, true); + isStartMark = true; + } + + uint64_t currentRecordTime = TimeStrToMilliseconds(MainStopWatchView::GetInstance()->GetShowTimelabel()->GetText()); // 获取当前时间 + uint64_t timeDifference = 0; // 时间差值 + if (lastRecordTime > 0) + { + // 如果不是第一次标记,则计算与上一次记录的时间差 + timeDifference = currentRecordTime - lastRecordTime; + } + // 将时间和时间差格式化为字符串,更新到UI + const char *formattedTime = MainStopWatchView::GetInstance()->GetShowTimelabel()->GetText(); + char formattedDiff[64] = {0}; + MillisecondsToTimeStr(timeDifference, formattedDiff); + // char *PickerData = (char *)malloc(128); + // if (lastRecordTime == 0) // 如果是第一次标记 + // { + // sprintf(PickerData, "%02d %s +%s", RecordCycleNumber, formattedTime, formattedTime); + // } + // else + // { + // sprintf(PickerData, "%02d %s +%s", RecordCycleNumber, formattedTime, formattedDiff); + // } + // m_listdata->PushFront(const_cast(PickerData)); + // m_listadapter->SetData(m_listdata); + // m_list->SetAdapter(m_listadapter); + // char PickerData[128]={0}; + // if (lastRecordTime == 0) // 如果是第一次标记 + // { + // sprintf(PickerData, "%02d %s +%s", RecordCycleNumber, formattedTime, formattedTime); + // } + // else + // { + // sprintf(PickerData, "%02d %s +%s", RecordCycleNumber, formattedTime, formattedDiff); + // } + + StopWatchItem item = {"", "", "", 0}; + char buffer[3] = {0}; // 足够存放两位数字及字符串结束符'\0' + std::sprintf(buffer, "%02d", RecordCycleNumber); + item.RecordCycleNumber = buffer; + item.formattedTime = std::string(formattedTime); + ; + item.formattedDiff = "+" + std::string((lastRecordTime == 0) ? formattedTime : formattedDiff); // lastRecordTime == 0,如果是第一次标记 + item.curSelectItemViewIndex = RecordCycleNumber - 1; + + view_->GetStopWatchAdapter()->setSelectedIndex(RecordCycleNumber - 1); + view_->GetStopWatchAdapter()->AddListItem(item); + m_list->SetAdapter(view_->GetStopWatchAdapter()); + m_list->SetStartIndex(RecordCycleNumber - 1); + m_list->SetSelectPosition(RecordCycleNumber); + m_list->RefreshList(); + // 保存当前时间为“上一次记录时间”,为下一次标记做准备 + lastRecordTime = currentRecordTime; + return true; + } + else if (strcmp(clickedViewId, ResetOrMarkButton_RESET2_VIEWID) == 0) // 点击重置按钮 + { + StopWatchModel::GetInstance()->StopWatch_StopTimer(); // 停止定时器 + mainStopWatchView->GetShowTimelabel()->SetText("00:00.00"); + lastRecordTime = 0; + view_->GetStopWatchAdapter()->ClearData(); + m_list->SetAdapter(nullptr); + m_list->RefreshList(); + + m_button->SetViewId(ResetOrMarkButton_RESET1_VIEWID); + m_button->SetImageSrc(ResetOrMarkButtonImg_Reset1, ResetOrMarkButtonImg_Reset1); + m_button->Invalidate(); + + if (isStartMark == true) // 重置标记 + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "isStartMark = %d", isStartMark); + mainStopWatchView->SetViewIsVisible(m_stopWatchlabel, true); + SetShowTimeLableStyle(m_showTimelabel, 0, 160, 84, 94); + mainStopWatchView->SetViewIsVisible(m_image, false); + mainStopWatchView->SetViewIsVisible(m_list, false); + isStartMark = false; + } + + // if (m_listdata != nullptr) + // { + // // 遍历列表,释放每个元素所占用的内存 + // ListNode *node = m_listdata->Head(); + // int cnt = 0; + // while (node != m_listdata->End()) + // { + // WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "%d", ++cnt); + // const char *p = node->data_; + // free(const_cast(p)); + + // node = m_listdata->Remove(node); + // } + // m_listdata->Clear(); + // } + // else + // { + // // Handle error or log the issue + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: m_listdata is nullptr"); + // } + RecordCycleNumber = 0; + } + else if (strcmp(clickedViewId, CycleToLimitReturnButton_VIEWID) == 0) // 点击返回按钮 + { + mainStopWatchView->ChangeView(STOPWATCH_RECORD_CYCLE_TO_LIMIT, MAIN_STOPWATCH); + } + else if (strcmp(clickedViewId, TimeToLimitReturnButton_VIEWID) == 0) // 点击返回按钮 + { + mainStopWatchView->ChangeView(STOPWATCH_RECORD_TIME_TO_LIMIT, MAIN_STOPWATCH); + } + else if (strcmp(clickedViewId, PlayOrPausecheckBoxVIEWID) == 0) // 点击播放和暂停按钮 + { + if (StopWatchModel::GetInstance()->isReachMaxRecordTime()) // 到达最大时间不能再计时 + { + mainStopWatchView->ChangeView(MAIN_STOPWATCH, STOPWATCH_RECORD_TIME_TO_LIMIT); + } + } + return true; + } + + bool MainStopWatchPresenter::OnChange(UICheckBox::UICheckBoxState state) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchPresenter::OnChange,state = %d", state); + if (state == UICheckBox::UICheckBoxState::SELECTED) + { + StopWatchModel::GetInstance()->StopWatch_StartTimer(STOPWATCH_TIMER_DURATION); // 开启定时器,如果定时器存在会直接返回 + StopWatchModel::GetInstance()->StopWatch_ResumeTimer(STOPWATCH_TIMER_DURATION); // 恢复定时器 + + m_button->SetViewId(ResetOrMarkButton_MARK_VIEWID); + m_button->SetImageSrc(ResetOrMarkButtonImg_Mark, ResetOrMarkButtonImg_Mark); + m_button->Invalidate(); // 图片重新赋值要刷新该区域 + TimerIsRunning = true; + } + else + { + StopWatchModel::GetInstance()->StopWatch_PauseTimer(); // 暂停定时器 + m_button->SetViewId(ResetOrMarkButton_RESET2_VIEWID); + m_button->SetImageSrc(ResetOrMarkButtonImg_Reset2, ResetOrMarkButtonImg_Reset2); + m_button->Invalidate(); + TimerIsRunning = false; + } + return true; + } + + // 增加按键事件 + bool MainStopWatchPresenter::OnKeyAct(UIView &view, const KeyEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchPresenter::OnKeyAct"); + uint16_t keyID = event.GetKeyId(); + uint16_t keyState = event.GetState(); + // 如果是power键就返回上一级 + if (keyID == static_cast(ZliteKeyCode::ZLITE_KEY_POWER) && keyState == 1 && uapi_get_screen_state() == 0) + { + NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS); + } + return false; + } + + void MainStopWatchPresenter::Notify() + { + if (view_->GetScrollView(MAIN_STOPWATCH) && view_->GetScrollView(MAIN_STOPWATCH)->IsVisible()) + { + if (TimerIsRunning) + { + view_->GetShowTimelabel()->SetText(StopWatchModel::GetInstance()->DisplayStopWatchDuration().c_str()); + view_->GetShowTimelabel()->Invalidate(); + } + } + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchView.cpp new file mode 100644 index 000000000..547ddf7af --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/MainStopWatchView.cpp @@ -0,0 +1,417 @@ +#include "stopwatch/include/MainStopWatchView.h" +#include "stopwatch/include/MainStopWatchPresenter.h" +#include "UiConfig.h" +#include "NativeAbility.h" +#include "AppViewIDs.h" +#include "wearable_log.h" +/*秒表主视图*/ +namespace OHOS +{ + + static MainStopWatchView *g_pMainStopWatchView{nullptr}; + + MainStopWatchView::MainStopWatchView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchView::MainStopWatchView"); + g_pMainStopWatchView = this; + } + + MainStopWatchView::~MainStopWatchView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchView::~MainStopWatchView"); + ClearAll(); + g_pMainStopWatchView = nullptr; + } + + MainStopWatchView *MainStopWatchView::GetInstance() + { + return g_pMainStopWatchView; + } + + void MainStopWatchView::ClearAll() + { + if (group != nullptr) + { + group->RemoveAll(); + scrollView[MAIN_STOPWATCH]->RemoveAll(); + + if (stopWatchlabel != nullptr) + { + delete stopWatchlabel; + stopWatchlabel = nullptr; + } + + if (showTimelabel != nullptr) + { + delete showTimelabel; + showTimelabel = nullptr; + } + + if (PlayOrPausecheckBox != nullptr) + { + delete PlayOrPausecheckBox; + PlayOrPausecheckBox = nullptr; + } + + if (ResetOrMarkbutton != nullptr) + { + delete ResetOrMarkbutton; + ResetOrMarkbutton = nullptr; + } + + if (LineImage != nullptr) + { + delete LineImage; + LineImage = nullptr; + } + + if (stopWatchAdapter != nullptr) + { + delete stopWatchAdapter; + stopWatchAdapter = nullptr; + } + + if (list != nullptr) + { + delete list; + list = nullptr; + } + + if (listadapter != nullptr) + { + delete listadapter; + listadapter = nullptr; + } + + if (listdata != nullptr) + { + listdata->Clear(); + delete listdata; + listdata = nullptr; + } + + if (scrollView[MAIN_STOPWATCH] != nullptr) + { + delete scrollView[MAIN_STOPWATCH]; + scrollView[MAIN_STOPWATCH] = nullptr; + } + + if (p_StopWatchRecordCycleToLimitView != nullptr) + { + delete p_StopWatchRecordCycleToLimitView; + p_StopWatchRecordCycleToLimitView = nullptr; + } + + if (p_StopWatchRecordTimeToLimitView != nullptr) + { + delete p_StopWatchRecordTimeToLimitView; + p_StopWatchRecordTimeToLimitView = nullptr; + } + + for (int i = MAIN_STOPWATCH; i < STOPWATCH_MAXVIEWID; i++) + { + scrollView[MAIN_STOPWATCH] = nullptr; + } + + delete group; + group = nullptr; + } + } + + /// @brief 设置视图是否可见 + /// @param view 具体视图 + /// @param status true 可见 false 不可见 + void MainStopWatchView::SetViewIsVisible(UIView *view, bool status) + { + if (status == true) + { + view->SetVisible(true); + } + else + { + view->SetVisible(false); + } + view->Invalidate(); + } + + // 1.切换到秒表主视图 + bool MainStopWatchView::ChangeMainStopWatch(int16_t thisView) + { + if (scrollView[thisView] == nullptr) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchView::ChangeMainStopWatch"); + group->Add(scrollView[thisView]); + } + return true; + } + + // 2.切换到秒表到达最高圈数视图 + bool MainStopWatchView::ChangeStopWatchRecordCycleLimit(int16_t thisView) + { + if (scrollView[thisView] == nullptr) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchView::StopWatchRecordCycleToLimitView"); + p_StopWatchRecordCycleToLimitView = new StopWatchRecordCycleToLimitView(); + if (p_StopWatchRecordCycleToLimitView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "MainStopWatchView:: new scrollView[%d] fail", thisView); + return false; + } + scrollView[thisView] = p_StopWatchRecordCycleToLimitView->InitStopWatchRecordCycleToLimitView(); + group->Add(scrollView[thisView]); + } + return true; + } + + // 3.切换到秒表到达最大时间计时视图 + bool MainStopWatchView::ChangeMainStopWatchRecordTimeLimit(int16_t thisView) + { + if (scrollView[thisView] == nullptr) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MainStopWatchView::ChangeMainStopWatchRecordTimeLimit"); + p_StopWatchRecordTimeToLimitView = new StopWatchRecordTimeToLimitView(); + if (p_StopWatchRecordTimeToLimitView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "MainStopWatchView:: new scrollView[%d] fail", thisView); + return false; + } + scrollView[thisView] = p_StopWatchRecordTimeToLimitView->InitStopWatchRecordTimeToLimitView(); + group->Add(scrollView[thisView]); + } + return true; + } + /* -------------------------------------------------------------------------- */ + // 1.MainStopWatchViewMapper:结构体定义了一个将视图ID映射到特定成员函数指针的映射表。 + struct MainStopWatchViewMapper + { + const int16_t viewId; + bool (MainStopWatchView::*func)(int16_t thisView); + }; + + // 2.ViewMapper[] 是一个静态的视图映射数组,将视图ID与MainStopWatchView类中的特定成员函数指针进行了绑定。 + static const MainStopWatchViewMapper ViewMapper[] = { + {MAIN_STOPWATCH, &MainStopWatchView::ChangeMainStopWatch}, + {STOPWATCH_RECORD_CYCLE_TO_LIMIT, &MainStopWatchView::ChangeStopWatchRecordCycleLimit}, + {STOPWATCH_RECORD_TIME_TO_LIMIT, &MainStopWatchView::ChangeMainStopWatchRecordTimeLimit}, + }; + + // 3.根据传入的interface参数执行相应视图ID关联的成员函数。 + bool MainStopWatchView::ClickFunc(int16_t interface) + { + int funcSize = sizeof(ViewMapper) / sizeof(ViewMapper[0]); + for (int i = 0; i < funcSize; i++) + { + if (interface == ViewMapper[i].viewId) + { + bool jug = (this->*(ViewMapper[i].func))(interface); + if (jug == false) + { + return false; + } + return true; + } + } + return false; + } + + // 4.切换视图 + void MainStopWatchView::ChangeView(int16_t hideView, int16_t showView) + { + if (hideView > STOPWATCH_MAXVIEWID) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "MainStopWatchView:: StopWatchViewId Overstep ones bounds"); + return; + } + scrollView[hideView]->SetVisible(false); + ClickFunc(showView); + scrollView[showView]->SetVisible(true); + Draw(); + } + /* -------------------------------------------------------------------------- */ + // 初始化秒表主视图 + void MainStopWatchView::InitMainStopWatchView() + { + if (group == nullptr) + { + /* ---------------------------------- group --------------------------------- */ + group = new UIViewGroup(); + if (group == nullptr) + { + return; + } + group->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight()); + /* ----------------------- scrollView[MAIN_STOPWATCH] ----------------------- */ + if (scrollView[MAIN_STOPWATCH] == nullptr) + { + scrollView[MAIN_STOPWATCH] = new UIScrollView(); + } + scrollView[MAIN_STOPWATCH]->SetPosition(0, 0, 466, 466); + scrollView[MAIN_STOPWATCH]->SetStyle(STYLE_BACKGROUND_OPA, 0xff); + scrollView[MAIN_STOPWATCH]->SetTouchable(true); + scrollView[MAIN_STOPWATCH]->SetDraggable(true); + scrollView[MAIN_STOPWATCH]->SetOnDragListener(presenter_); + /* ----------------------------- stopWatchlabel ----------------------------- */ + stopWatchlabel = new UILabelExt(); + if (stopWatchlabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stopWatchlabel new fail!!"); + return; + } + stopWatchlabel->SetPosition(83, 50, 300, 35); + stopWatchlabel->SetStyle(STYLE_TEXT_FONT, 30); + stopWatchlabel->SetStyle(STYLE_LINE_HEIGHT, 35); + stopWatchlabel->SetTextId(STR_STOPWATCH); // 秒表 + stopWatchlabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + stopWatchlabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + stopWatchlabel->SetRollSpeed(23); + stopWatchlabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + stopWatchlabel->SetVisible(true); + /* ------------------------------ showTimelabel ----------------------------- */ + showTimelabel = new UILabelExt(); + if (showTimelabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "showTimelabel new fail!!"); + return; + } + showTimelabel->SetPosition(0, 160, 466, 94); + showTimelabel->SetStyle(STYLE_TEXT_FONT, 84); + showTimelabel->SetStyle(STYLE_LINE_HEIGHT, 94); + showTimelabel->SetText("00:00.00"); + showTimelabel->SetLineBreakMode(UILabel::LINE_BREAK_CLIP); + showTimelabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + showTimelabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, 84); + /* -------------------------------- LineImage ------------------------------- */ + LineImage = new UIImageView(); + if (LineImage == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LineImage new fail!!"); + return; + } + LineImage->SetPosition(53, 150); + const char *imageimagesPath = "/user/res/stopwatch/STOPWATCH_LINE.bin"; + LineImage->SetSrc(imageimagesPath); + LineImage->SetVisible(false); + /* ---------------------------- stopWatchAdapter ---------------------------- */ + stopWatchAdapter = new StopWatchAdapter(); + if (stopWatchAdapter == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stopWatchAdapter new fail!!"); + return; + } + /* ---------------------------------- list ---------------------------------- */ + list = new UIList(); + if (list == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "list new fail!!"); + return; + } + list->SetPosition(56, 170, 360, 130); + list->SetStyle(STYLE_BACKGROUND_COLOR, 0xff000000); + list->SetReboundSize(30); + list->SetThrowDrag(true); + list->SetIntercept(true); + list->SetMaxScrollDistance(1000); + list->SetDragACCLevel(5); + list->SetSwipeACCLevel(200); /*设置手指抬起屏幕后的补偿距离。*/ + list->SetVisible(false); + list->RequestFocus(); + list->SetRotateFactor(1.0); + /* ------------------------------- listadapter ------------------------------ */ + listadapter = new TextAdapter(); + if (listadapter == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "listadapter new fail!!"); + return; + } + listadapter->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, 28); + listadapter->SetWidth(356); + listadapter->SetHeight(32); + listadapter->SetLineBreakMode(UILabel::LINE_BREAK_CLIP); + /* -------------------------------- listdata -------------------------------- */ + listdata = new List(); + if (listdata == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "listdata new fail!!"); + return; + } + /* --------------------------- PlayOrPausecheckBox -------------------------- */ + PlayOrPausecheckBox = new UICheckBox(); + if (PlayOrPausecheckBox == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "PlayOrPausecheckBox new fail!!"); + return; + } + PlayOrPausecheckBox->SetPosition(118, 321, 120, 120); + PlayOrPausecheckBox->SetViewId(PlayOrPausecheckBoxVIEWID); + PlayOrPausecheckBox->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff); + PlayOrPausecheckBox->SetStyle(STYLE_BORDER_RADIUS, 51); + PlayOrPausecheckBox->SetImages(checkBox1selectedImg, checkBox1unSelectedImg); + PlayOrPausecheckBox->SetVisible(true); + /* ---------------------------- ResetOrMarkbutton --------------------------- */ + ResetOrMarkbutton = new UIButton(); + if (ResetOrMarkbutton == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ResetOrMarkbutton new fail!!"); + return; + } + ResetOrMarkbutton->SetPosition(256, 333, 100, 100); + ResetOrMarkbutton->SetViewId(ResetOrMarkButton_RESET1_VIEWID); + ResetOrMarkbutton->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff); + ResetOrMarkbutton->SetStyle(STYLE_BACKGROUND_OPA, 0x00); + ResetOrMarkbutton->SetImageSrc(ResetOrMarkButtonImg_Reset1, ResetOrMarkButtonImg_Reset1); + ResetOrMarkbutton->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xfffbfbfb, UIButton::PRESSED); + ResetOrMarkbutton->SetStyleForState(STYLE_BACKGROUND_OPA, 0x00, UIButton::PRESSED); + ResetOrMarkbutton->SetStyleForState(STYLE_BORDER_COLOR, 0xff0b1928, UIButton::PRESSED); + ResetOrMarkbutton->SetVisible(true); + /* -------------------------------------------------------------------------- */ + MainStopWatchPresenter::GetInstance()->SetCheckBoxAndButton(PlayOrPausecheckBox, ResetOrMarkbutton); + MainStopWatchPresenter::GetInstance()->SetLable(stopWatchlabel, showTimelabel); + MainStopWatchPresenter::GetInstance()->SetImage(LineImage); + MainStopWatchPresenter::GetInstance()->SetList(list, listadapter, listdata); + // Add the CallBack about events + PlayOrPausecheckBox->SetOnChangeListener(presenter_); + PlayOrPausecheckBox->SetOnClickListener(presenter_); + ResetOrMarkbutton->SetOnClickListener(presenter_); + } + } + + UILabelExt *MainStopWatchView::GetShowTimelabel(void) + { + return showTimelabel; + } + + UICheckBox *MainStopWatchView::GetPlayOrPausecheckBox(void) + { + return PlayOrPausecheckBox; + } + + /*切换到记录时间到达上线视图*/ + void MainStopWatchView::ChangeRecordTimeToLimitView(void) + { + ChangeView(MAIN_STOPWATCH, STOPWATCH_RECORD_TIME_TO_LIMIT); + } + + UIScrollView *MainStopWatchView::GetScrollView(int16_t index) + { + return scrollView[index]; + } + + StopWatchAdapter *MainStopWatchView::GetStopWatchAdapter(void) + { + return stopWatchAdapter; + } + + void MainStopWatchView::OnStart() + { + InitMainStopWatchView(); + + scrollView[MAIN_STOPWATCH]->Add(stopWatchlabel); + scrollView[MAIN_STOPWATCH]->Add(showTimelabel); + scrollView[MAIN_STOPWATCH]->Add(LineImage); + scrollView[MAIN_STOPWATCH]->Add(list); + scrollView[MAIN_STOPWATCH]->Add(PlayOrPausecheckBox); + scrollView[MAIN_STOPWATCH]->Add(ResetOrMarkbutton); + group->Add(scrollView[MAIN_STOPWATCH]); + AddViewToRootContainer(group); + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchAdapter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchAdapter.cpp new file mode 100644 index 000000000..352b06c23 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchAdapter.cpp @@ -0,0 +1,83 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-12-12 11:07:26 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-12-16 11:43:35 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/src/StopWatchAdapter.cpp + */ +#include "stopwatch/include/StopWatchAdapter.h" +#include "stopwatch/include/StopWatchItemView.h" +#include "wearable_log.h" +namespace OHOS +{ + StopWatchAdapter::StopWatchAdapter() {} + StopWatchAdapter::~StopWatchAdapter() + { + listData.clear(); + } + uint16_t StopWatchAdapter::GetCount(void) + { + return listData.size(); + } + + void StopWatchAdapter::ClearData(void) + { + listData.clear(); + curSelectItemViewIndex = -1; + } + + void StopWatchAdapter::setSelectedIndex(int index) + { + curSelectItemViewIndex = index; + } + + UIView *StopWatchAdapter::GetView(UIView *inView, int16_t index) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetView:%d", index); + if (listData.empty()) + { + return nullptr; + } + if (index < 0) + { + return nullptr; + } + size_t uindex = index; + if (uindex >= listData.size()) + { + return nullptr; + } + + std::list::iterator it = listData.begin(); + for (int i = 0; i < index; i++) + { + it++; + } + const StopWatchItem itemData = *it; + StopWatchItemView *item = nullptr; + if (inView == nullptr) + { + item = new StopWatchItemView(); + } + else + { + item = static_cast(inView); + } + item->SetViewIndex(index); + item->SetItemInfo(itemData); + if(curSelectItemViewIndex == itemData.curSelectItemViewIndex) + { + item->SetItemViewColor(true); + } + else + { + item->SetItemViewColor(false); + } + return item; + } + + void StopWatchAdapter::AddListItem(const StopWatchItem &item) + { + listData.push_front(item); + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchItemView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchItemView.cpp new file mode 100644 index 000000000..c632d8c19 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchItemView.cpp @@ -0,0 +1,74 @@ +/* + * @Author: luozheng 1732036298@qq.com + * @Date: 2024-12-12 14:40:44 + * @LastEditors: luozheng 1732036298@qq.com + * @LastEditTime: 2024-12-16 11:40:34 + * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/stopwatch/src/StopWatchItemView.cpp + */ +#include "stopwatch/include/StopWatchItemView.h" +#include "wearable_log.h" +namespace OHOS +{ + StopWatchItemView::StopWatchItemView() + { + SetPosition(0, 0, 360, 42); + SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full); + SetStyle(STYLE_BACKGROUND_OPA, 255); + SetUpChild(); + Add(&RecordCycleNumber); + Add(&formattedTime); + Add(&formattedDiff); + } + + StopWatchItemView::~StopWatchItemView() + { + RemoveAll(); + } + + void StopWatchItemView::SetItemInfo(const StopWatchItem itemInfo) + { + RecordCycleNumber.SetText(itemInfo.RecordCycleNumber.c_str()); + formattedTime.SetText(itemInfo.formattedTime.c_str()); + formattedDiff.SetText(itemInfo.formattedDiff.c_str()); + } + + void StopWatchItemView::SetUpChild() + { + RecordCycleNumber.SetPosition(0, 0, 80, 32); + RecordCycleNumber.SetStyle(STYLE_TEXT_FONT, 28); + RecordCycleNumber.SetStyle(STYLE_LINE_HEIGHT, 32); + RecordCycleNumber.SetLineBreakMode(UILabel::LINE_BREAK_CLIP); + RecordCycleNumber.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + RecordCycleNumber.SetFont(DEFAULT_VECTOR_FONT_FILENAME, 28); + + formattedTime.SetPosition(80, 0, 120, 32); + formattedTime.SetStyle(STYLE_TEXT_FONT, 28); + formattedTime.SetStyle(STYLE_LINE_HEIGHT, 32); + formattedTime.SetLineBreakMode(UILabel::LINE_BREAK_CLIP); + formattedTime.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + formattedTime.SetFont(DEFAULT_VECTOR_FONT_FILENAME, 28); + + formattedDiff.SetPosition(230, 0, 130, 32); + formattedDiff.SetStyle(STYLE_TEXT_FONT, 28); + formattedDiff.SetStyle(STYLE_LINE_HEIGHT, 32); + formattedDiff.SetLineBreakMode(UILabel::LINE_BREAK_CLIP); + formattedDiff.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + formattedDiff.SetFont(DEFAULT_VECTOR_FONT_FILENAME, 28); + } + + void StopWatchItemView::SetItemViewColor(bool flag) + { + if (flag) + { + RecordCycleNumber.SetTextColor(Color::GetColorFromRGBA(0xff, 0x8a, 0x36, 0xff)); + formattedTime.SetTextColor(Color::GetColorFromRGBA(0xff, 0x8a, 0x36, 0xff)); + formattedDiff.SetTextColor(Color::GetColorFromRGBA(0xff, 0x8a, 0x36, 0xff)); + } + else + { + RecordCycleNumber.SetTextColor(Color::GetColorFromRGBA(0xaa, 0xaa, 0xaa, 0xff)); + formattedTime.SetTextColor(Color::GetColorFromRGBA(0xaa, 0xaa, 0xaa, 0xff)); + formattedDiff.SetTextColor(Color::GetColorFromRGBA(0xaa, 0xaa, 0xaa, 0xff)); + } + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchModel.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchModel.cpp new file mode 100644 index 000000000..ff9d68503 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchModel.cpp @@ -0,0 +1,210 @@ +#include "stopwatch/include/StopWatchModel.h" +#include "cmsis_os.h" +#include +#include +#include "custom_utils.h" +#include "wearable_log.h" +#include +#include "stopwatch/include/MainStopWatchView.h" +namespace OHOS +{ + + std::shared_ptr StopWatchModel::GetInstance() // shared_ptr:当没有引用指向这个实例时会自动释放内存 + { + static std::shared_ptr instance(new StopWatchModel()); + return instance; + } + + /* ----------------------------------- 定时器 ---------------------------------- */ + // 声明定时器变量 + static osTimerId_t g_timer = nullptr; + static uint32_t g_StopWatchTimes = {0}; + static constexpr int32 NUM_TEN = 10; // 主要用于格式化输出,当小时、分钟或秒小于10时,在其前面添加一个’0’以保持常规时间格式 + static constexpr int16 ERROR = 0; + static constexpr int16 SUCCESS = 1; + static constexpr int16 NUM_TIME_MIN = 60; + static constexpr int16 NUM_TIME_HOUR = 3600; + static constexpr int32 NUM_TIME_DAY = 86400; + static constexpr uint32_t MAX_STOPWATCH_TIME = (99 * 60 * 1000) + (59 * 1000) + 990; // 99分59秒990毫秒 + static uint64_t g_timerStartTimestamp = 0; // 添加一个全局变量来存储定时器开始的时间戳 + /* + * @brief 显示倒计时(分钟、秒、毫秒),毫秒显示为两位数 + */ + std::string StopWatchModel::DisplayStopWatchDuration() + { + stopwatchDuration.erase(); + std::string minute; + std::string seconds; + std::string milliseconds; + + // 假设 g_StopWatchTimes 是毫秒数 + int min = g_StopWatchTimes / (60 * 1000); // 60,000 毫秒 = 1 分钟 + int sec = (g_StopWatchTimes % (60 * 1000)) / 1000; // 1,000 毫秒 = 1 秒 + int msec = (g_StopWatchTimes % 1000) / 10; // 获得两位数的毫秒,最大值为99 + + if (min < 10) + { + minute = "0" + std::to_string(min); + } + else + { + minute = std::to_string(min); + } + + if (sec < 10) + { + seconds = "0" + std::to_string(sec); + } + else + { + seconds = std::to_string(sec); + } + + // 格式化毫秒为两位数 + if (msec < 10) + { + milliseconds = "0" + std::to_string(msec); + } + else + { + milliseconds = std::to_string(msec); + } + + // 拼接分钟、秒和毫秒 + stopwatchDuration = minute + ":" + seconds + "." + milliseconds; + + return stopwatchDuration.c_str(); + } + + // 检查是否达到最大记录时间 + bool StopWatchModel::isReachMaxRecordTime(void) + { + if (g_StopWatchTimes >= MAX_STOPWATCH_TIME) + { + return true; + } + return false; + } + + static void StopWatch_TimerCallbackProc(int data) + { + if (MainStopWatchView::GetInstance() == nullptr) + { + return; + } + MainStopWatchView::GetInstance()->GetPlayOrPausecheckBox()->SetState(UICheckBox::UNSELECTED); + MainStopWatchView::GetInstance()->ChangeRecordTimeToLimitView(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "已到达记录最高时间:%d",g_StopWatchTimes); + g_StopWatchTimes = MAX_STOPWATCH_TIME; + MainStopWatchView::GetInstance()->GetShowTimelabel()->SetText(StopWatchModel::GetInstance()->DisplayStopWatchDuration().c_str()); + uapi_set_screen_on_api(); + } + + /* + * @brief 倒计时回调函数 + */ + static void StopWatch_TimerCallback(int data) + { + g_StopWatchTimes += 10; // 每次回调增加10毫秒 + if(StopWatchModel::GetInstance()->isReachMaxRecordTime()) //达到最大时间 + { + GraphicService::GetInstance()->PostGraphicEvent(std::bind(StopWatch_TimerCallbackProc, data)); + } + } + + /* + * @brief 开启定时器函数 + * @param interval 时间间隔,单位ms + */ + void StopWatchModel::StopWatch_StartTimer(uint32_t interval) + { + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_timer != nullptr) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopWatchModel::StopWatch_StartTimer Timer already exists!!"); + return; + } + + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_timer = osTimerNew((osTimerFunc_t)StopWatch_TimerCallback, osTimerPeriodic, nullptr, nullptr); + // 检查定时器创建是否成功 + if (g_timer == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StopWatchModel::StopWatch_StartTimer Timer create failed!!"); + return; + } + + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + + /* --------------------------------- 4.启动定时器 -------------------------------- */ + // g_timerStartTimestamp = GetCurrentTimestamp(); // 假设GetCurrentTimestamp()是获取当前时间戳的函数 + osStatus_t ret = osTimerStart(g_timer, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[StopWatch_StartTimer]osTimerDelete failed, ret = %lx!!", ret); + if (g_timer != nullptr) + { + ret = osTimerDelete(g_timer); + } + g_timer = nullptr; + return; + } + return; + } + + /* + * @brief 停止定时器 + */ + void StopWatchModel::StopWatch_StopTimer(void) + { + // 检查定时器是否存在 + if (g_timer != nullptr) + { + osTimerStop(g_timer); + // 删除定时器并置为 nullptr + osStatus_t ret = osTimerDelete(g_timer); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScanTimerCallback osTimerDelete failed, ret = %lx!!", ret); + } + g_timer = nullptr; + g_StopWatchTimes = 0; + } + } + /* + * @brief 暂停定时器 + */ + void StopWatchModel::StopWatch_PauseTimer(void) + { + // 检查定时器是否存在 + if (g_timer != nullptr) + { + // 暂停定时器,但不删除它 + osStatus_t ret = osTimerStop(g_timer); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StopWatch_PauseTimer osTimerStop failed, ret = %lx!!", ret); + } + } + } + + /* + * @brief 恢复定时器 + */ + void StopWatchModel::StopWatch_ResumeTimer(uint32_t interval) + { + // 检查定时器是否存在 + if (g_timer != nullptr) + { + int tick = osMs2Tick(interval); + // 恢复定时器 + osStatus_t ret = osTimerStart(g_timer, tick); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StopWatch_ResumeTimer osTimerStart failed, ret = %lx!!", ret); + } + } + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordCycleToLimitView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordCycleToLimitView.cpp new file mode 100644 index 000000000..a6bf75f58 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordCycleToLimitView.cpp @@ -0,0 +1,156 @@ +#include "stopwatch/include/StopWatchRecordCycleToLimitView.h" +#include "stopwatch/include/MainStopWatchPresenter.h" +#include "UiConfig.h" +#include "wearable_log.h" +/*弹窗视图:到达最高圈数99时弹出*/ +namespace OHOS +{ + + static StopWatchRecordCycleToLimitView *g_pStopWatchRecordCycleToLimitView{nullptr}; + + StopWatchRecordCycleToLimitView::StopWatchRecordCycleToLimitView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopWatchRecordCycleToLimitView::StopWatchRecordCycleToLimitView"); + g_pStopWatchRecordCycleToLimitView = this; + } + + StopWatchRecordCycleToLimitView::~StopWatchRecordCycleToLimitView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopWatchRecordCycleToLimitView::~StopWatchRecordCycleToLimitView"); + ClearAll(); + g_pStopWatchRecordCycleToLimitView = nullptr; + } + + StopWatchRecordCycleToLimitView *StopWatchRecordCycleToLimitView::GetInstance() + { + return g_pStopWatchRecordCycleToLimitView; + } + // 初始化秒表到达最高圈数时弹出的视图 + UIScrollView *StopWatchRecordCycleToLimitView::InitStopWatchRecordCycleToLimitView() + { + if (scrollView == nullptr) + { + scrollView = new UIScrollView(); + scrollView->SetPosition(0, 0, 466, 466); + scrollView->SetStyle(STYLE_BACKGROUND_OPA, 0xff); + scrollView->SetTouchable(true); + scrollView->SetDraggable(true); + UIView::OnDragListener *draglistener = static_cast(MainStopWatchPresenter::GetInstance()); + if (draglistener == nullptr) + { + return nullptr; + } + scrollView->SetOnDragListener(draglistener); + /* -------------------------------------------------------------------------- */ + if (Title == nullptr) + { + Title = new UILabelExt(); + if (Title == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Title new fail"); + return nullptr; + } + } + Title->SetPosition(83, 50, 300, 35); + Title->SetStyle(STYLE_TEXT_FONT, 30); + Title->SetStyle(STYLE_LINE_HEIGHT, 35); + Title->SetTextId(STR_STOPWATCH); // 秒表 + Title->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + Title->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + Title->SetRollSpeed(23); + Title->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* -------------------------------------------------------------------------- */ + if (AttentionImage == nullptr) + { + AttentionImage = new UIImageView(); + if (AttentionImage == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AttentionImage new fail"); + return nullptr; + } + } + AttentionImage->SetPosition(193, 121, 100, 100); + AttentionImage->SetStyle(STYLE_BORDER_RADIUS, 100); + AttentionImage->SetSrc(PNG_ATTENTION_IMAGE); + /* -------------------------------------------------------------------------- */ + if (AttentionLabel == nullptr) + { + AttentionLabel = new UILabelExt(); + if (AttentionLabel == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AttentionLabel new fail"); + return nullptr; + } + } + AttentionLabel->SetPosition(83, 253, 300, 35); + AttentionLabel->SetStyle(STYLE_TEXT_FONT, 30); + AttentionLabel->SetStyle(STYLE_LINE_HEIGHT, 35); + AttentionLabel->SetTextId(STR_TMCHBR); // 当前已达到了最高计数 + AttentionLabel->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + AttentionLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + AttentionLabel->SetTextColor(Color::GetColorFromRGBA(0xaa, 0xaa, 0xaa, 0xff)); + AttentionLabel->SetRollSpeed(23); + AttentionLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* -------------------------------------------------------------------------- */ + if (button == nullptr) + { + button = new UILabelButtonExt(); + if (button == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "button new fail"); + return nullptr; + } + } + button->SetPosition(0, 366, 466, 100); + button->SetViewId(CycleToLimitReturnButton_VIEWID); + button->SetImageSrc(PNG_466x100BUTTON_IMAGE, PNG_466x100BUTTON_IMAGE); + button->SetTextId(STR_KONW); + button->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + button->SetStyle(STYLE_LINE_HEIGHT, 35); + button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff000000, UIButton::PRESSED); + UIView::OnClickListener *buttonClick = static_cast(MainStopWatchPresenter::GetInstance()); + if (buttonClick == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "buttonClick new fail"); + return nullptr; + } + button->SetOnClickListener(buttonClick); + /* ----------------------------------- Add ---------------------------------- */ + scrollView->Add(Title); + scrollView->Add(AttentionImage); + scrollView->Add(AttentionLabel); + scrollView->Add(button); + } + return scrollView; + } + + void StopWatchRecordCycleToLimitView::ClearAll() + { + if (scrollView != nullptr) + { + scrollView->RemoveAll(); + if (Title != nullptr) + { + delete Title; + Title = nullptr; + } + if (AttentionImage != nullptr) + { + delete AttentionImage; + AttentionImage = nullptr; + } + if (AttentionLabel != nullptr) + { + delete AttentionLabel; + AttentionLabel = nullptr; + } + if (button != nullptr) + { + delete button; + button = nullptr; + } + delete scrollView; + scrollView = nullptr; + } + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordTimeToLimitView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordTimeToLimitView.cpp new file mode 100644 index 000000000..403064dfd --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/stopwatch/src/StopWatchRecordTimeToLimitView.cpp @@ -0,0 +1,178 @@ +#include "stopwatch/include/StopWatchRecordTimeToLimitView.h" +#include "stopwatch/include/MainStopWatchPresenter.h" +#include "UiConfig.h" +#include "wearable_log.h" +/*弹窗视图:到达最高时间99:59.99时弹出*/ +namespace OHOS +{ + + static StopWatchRecordTimeToLimitView *g_pStopWatchRecordTimeToLimitView{nullptr}; + + StopWatchRecordTimeToLimitView::StopWatchRecordTimeToLimitView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopWatchRecordTimeToLimitView::StopWatchRecordTimeToLimitView"); + g_pStopWatchRecordTimeToLimitView = this; + } + + StopWatchRecordTimeToLimitView::~StopWatchRecordTimeToLimitView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StopWatchRecordTimeToLimitView::~StopWatchRecordTimeToLimitView"); + ClearAll(); + g_pStopWatchRecordTimeToLimitView = nullptr; + } + + StopWatchRecordTimeToLimitView *StopWatchRecordTimeToLimitView::GetInstance() + { + + return g_pStopWatchRecordTimeToLimitView; + } + + UIScrollView *StopWatchRecordTimeToLimitView::InitStopWatchRecordTimeToLimitView() + { + if (scrollView == nullptr) + { + scrollView = new UIScrollView(); + scrollView->SetPosition(0, 0, 466, 466); + scrollView->SetStyle(STYLE_BACKGROUND_OPA, 0xff); + scrollView->SetTouchable(true); + scrollView->SetDraggable(true); + UIView::OnDragListener *draglistener = static_cast(MainStopWatchPresenter::GetInstance()); + if (draglistener == nullptr) + { + return nullptr; + } + scrollView->SetOnDragListener(draglistener); + /* -------------------------------------------------------------------------- */ + if (Title == nullptr) + { + Title = new UILabelExt(); + if (Title == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Title new fail"); + return nullptr; + } + } + Title->SetPosition(83, 50, 300, 35); + Title->SetStyle(STYLE_TEXT_FONT, 30); + Title->SetStyle(STYLE_LINE_HEIGHT, 35); + Title->SetTextId(STR_STOPWATCH); // 秒表 + Title->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + Title->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + Title->SetRollSpeed(23); + Title->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* -------------------------------------------------------------------------- */ + if (AttentionImage == nullptr) + { + AttentionImage = new UIImageView(); + if (AttentionImage == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AttentionImage new fail"); + return nullptr; + } + } + AttentionImage->SetPosition(193, 121, 100, 100); + AttentionImage->SetStyle(STYLE_BORDER_RADIUS, 100); + AttentionImage->SetSrc(PNG_ATTENTION_IMAGE); + /* ---------------------------- AttentionLabel_1 ---------------------------- */ + if (AttentionLabel_1 == nullptr) + { + AttentionLabel_1 = new UILabelExt(); + if (AttentionLabel_1 == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AttentionLabel_1 new fail"); + return nullptr; + } + } + AttentionLabel_1->SetPosition(83, 235, 300, 35); + AttentionLabel_1->SetStyle(STYLE_TEXT_FONT, 30); + AttentionLabel_1->SetStyle(STYLE_LINE_HEIGHT, 35); + AttentionLabel_1->SetTextId(STR_MAXIMUM_TIME_REACH_NOTE); // 当前已达到了最长时间 + AttentionLabel_1->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + AttentionLabel_1->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + AttentionLabel_1->SetTextColor(Color::GetColorFromRGBA(0xaa, 0xaa, 0xaa, 0xff)); + AttentionLabel_1->SetRollSpeed(23); + AttentionLabel_1->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* ---------------------------- AttentionLabel_2 ---------------------------- */ + if (AttentionLabel_2 == nullptr) + { + AttentionLabel_2 = new UILabelExt(); + if (AttentionLabel_2 == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AttentionLabel_2 new fail"); + return nullptr; + } + } + AttentionLabel_2->SetPosition(53, 279, 360, 35); + AttentionLabel_2->SetStyle(STYLE_TEXT_FONT, 30); + AttentionLabel_2->SetStyle(STYLE_LINE_HEIGHT, 35); + AttentionLabel_2->SetTextId(STR_STOPWATCH_STOP_NOTE); // 秒表自动暂停,请重新开始 + AttentionLabel_2->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + AttentionLabel_2->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + AttentionLabel_2->SetTextColor(Color::GetColorFromRGBA(0xaa, 0xaa, 0xaa, 0xff)); + AttentionLabel_2->SetRollSpeed(23); + AttentionLabel_2->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* -------------------------------------------------------------------------- */ + if (button == nullptr) + { + button = new UILabelButtonExt(); + if (button == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "button new fail"); + return nullptr; + } + } + button->SetPosition(0, 366, 466, 100); + button->SetViewId(TimeToLimitReturnButton_VIEWID); + button->SetImageSrc(PNG_466x100BUTTON_IMAGE, PNG_466x100BUTTON_IMAGE); + button->SetTextId(STR_KONW); + button->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + button->SetStyle(STYLE_LINE_HEIGHT, 35); + button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff000000, UIButton::PRESSED); + UIView::OnClickListener *buttonClick = static_cast(MainStopWatchPresenter::GetInstance()); + if (buttonClick == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "buttonClick new fail"); + return nullptr; + } + button->SetOnClickListener(buttonClick); + /* ----------------------------------- Add ---------------------------------- */ + scrollView->Add(Title); + scrollView->Add(AttentionImage); + scrollView->Add(AttentionLabel_1); + scrollView->Add(AttentionLabel_2); + scrollView->Add(button); + } + return scrollView; + } + + void StopWatchRecordTimeToLimitView::ClearAll() + { + if (scrollView != nullptr) + { + scrollView->RemoveAll(); + if (Title != nullptr) + { + delete Title; + Title = nullptr; + } + if (AttentionImage != nullptr) + { + delete AttentionImage; + AttentionImage = nullptr; + } + if (AttentionLabel_1 != nullptr) + { + delete AttentionLabel_1; + AttentionLabel_1 = nullptr; + } + if (button != nullptr) + { + delete button; + button = nullptr; + } + + delete scrollView; + scrollView = nullptr; + } + } +} \ No newline at end of file diff --git a/code/sdk/build/config/target_config/brandy/config.py b/code/sdk/build/config/target_config/brandy/config.py index 41e18ef61..6f8e33d6d 100644 --- a/code/sdk/build/config/target_config/brandy/config.py +++ b/code/sdk/build/config/target_config/brandy/config.py @@ -386,8 +386,8 @@ target = { # "ppg_sensor", # "ppgBleService", # "mag_sensor", - # "vibrator", - # "vibrator_service", + "vibrator", + "vibrator_service", # "lwIP", # "slip", # "cat1_service", -- 2.17.1