--- /dev/null
+/*
+ * @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
--- /dev/null
+/*
+ * @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
--- /dev/null
+/*
+ * @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 <cstdint>
+#include <iostream>
+#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
--- /dev/null
+/*
+ * @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<RespiratoryTrainingView>,
+ 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
--- /dev/null
+/*
+ * @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 <components/ui_label_button_ext.h>
+#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<RespiratoryTrainingPresenter>, 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
--- /dev/null
+/*
+ * @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<UIView::OnClickListener *>(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
--- /dev/null
+/*
+ * @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<UIView::OnDragListener *>(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<UIView::OnClickListener *>(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();
+ }
+ }
+}
--- /dev/null
+/*
+ * @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 <cmsis_os2.h>
+#include <cmsis_os.h>
+#include <ohos_types.h>
+#include <service/graphic_service.h>
+#include <iostream>
+#include "respiratorytraining/include/RespiratoryTrainingView.h"
+#include <custom_utils.h>
+#include "gfx_utils/mem_check.h"
+#include "ConfigModel.h"
+
+#include <chrono>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <unordered_map>
+#include <custom_runtime.h>
+#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<uint32_t>(std::chrono::duration_cast<std::chrono::microseconds>(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;
+ }
+ }
+}
--- /dev/null
+/*
+ * @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 <custom_utils.h>
+#include "UiConfig.h"
+#include <iostream>
+#include <string>
+#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<RespiratoryTrainingView>::OnPause();
+ }
+
+ void RespiratoryTrainingPresenter::OnResume(void)
+ {
+ Presenter<RespiratoryTrainingView>::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<std::string, int> 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<uint16_t>(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
--- /dev/null
+/*
+ * @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 <custom_runtime.h>
+#include <custom_utils.h>
+
+#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<float> 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<float>(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<float>(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
# "ppg_sensor",
# "ppgBleService",
# "mag_sensor",
- # "vibrator",
- # "vibrator_service",
+ "vibrator",
+ "vibrator_service",
# "lwIP",
# "slip",
# "cat1_service",