1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H 18 19 #include <algorithm> 20 #include <vector> 21 22 #include "base/geometry/ng/offset_t.h" 23 #include "core/animation/spring_curve.h" 24 #include "core/common/container.h" 25 #include "core/components_ng/base/modifier.h" 26 #include "core/components_ng/pattern/radio/radio_modifier.h" 27 #include "core/components_ng/pattern/toggle/switch_paint_property.h" 28 #include "core/components_ng/property/property.h" 29 #include "core/components_ng/render/animation_utils.h" 30 #include "core/components_ng/render/canvas_image.h" 31 #include "core/components_ng/render/drawing_forward.h" 32 #include "core/components_ng/render/paint_wrapper.h" 33 namespace OHOS::Ace::NG { 34 class SwitchModifier : public ContentModifier { 35 DECLARE_ACE_TYPE(SwitchModifier, ContentModifier); 36 37 public: 38 SwitchModifier(bool isSelect, const Color& boardColor, float dragOffsetX); 39 ~SwitchModifier() override = default; 40 onDraw(DrawingContext & context)41 void onDraw(DrawingContext& context) override 42 { 43 RSCanvas& canvas = context.canvas; 44 PaintSwitch(canvas, offset_->Get(), size_->Get()); 45 } 46 UpdateAnimatableProperty()47 void UpdateAnimatableProperty() 48 { 49 switch (touchHoverType_) { 50 case TouchHoverAnimationType::HOVER: 51 SetBoardColor(LinearColor(hoverColor_), hoverDuration_, Curves::FRICTION); 52 break; 53 case TouchHoverAnimationType::PRESS_TO_HOVER: 54 SetBoardColor(LinearColor(hoverColor_), hoverToTouchDuration_, Curves::SHARP); 55 break; 56 case TouchHoverAnimationType::NONE: 57 SetBoardColor(LinearColor(hoverColor_.BlendOpacity(0)), hoverDuration_, Curves::FRICTION); 58 break; 59 case TouchHoverAnimationType::HOVER_TO_PRESS: 60 SetBoardColor(LinearColor(clickEffectColor_), hoverToTouchDuration_, Curves::SHARP); 61 break; 62 case TouchHoverAnimationType::PRESS: 63 SetBoardColor(LinearColor(clickEffectColor_), hoverDuration_, Curves::FRICTION); 64 break; 65 default: 66 break; 67 } 68 // Animation is not displayed when created for the first time. 69 if (isFirstCreated_) { 70 animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 71 pointOffset_->Set(isSelect_->Get() ? size_->Get().Width() - size_->Get().Height() : 0.0f); 72 isFirstCreated_ = false; 73 } 74 AnimationOption colorOption = AnimationOption(); 75 colorOption.SetDuration(colorAnimationDuration_); 76 colorOption.SetCurve(Curves::FAST_OUT_SLOW_IN); 77 AnimationUtils::Animate(colorOption, [&]() { 78 animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 79 }); 80 81 AnimationOption pointOption = AnimationOption(); 82 pointOption.SetDuration(pointAnimationDuration_); 83 pointOption.SetCurve(Curves::FAST_OUT_SLOW_IN); 84 float newPointOffset = 0.0f; 85 if (!isDragEvent_) { 86 newPointOffset = isSelect_->Get() ? size_->Get().Width() - size_->Get().Height() : 0.0f; 87 } else { 88 newPointOffset = std::clamp( 89 dragOffsetX_->Get() - offset_->Get().GetX(), 0.0f, size_->Get().Width() - size_->Get().Height()); 90 } 91 AnimationUtils::Animate(pointOption, [&]() { pointOffset_->Set(newPointOffset); }); 92 } 93 SetBoardColor(LinearColor color,int32_t duratuion,const RefPtr<CubicCurve> & curve)94 void SetBoardColor(LinearColor color, int32_t duratuion, const RefPtr<CubicCurve>& curve) 95 { 96 if (animateTouchHoverColor_) { 97 AnimationOption option = AnimationOption(); 98 option.SetDuration(duratuion); 99 option.SetCurve(curve); 100 AnimationUtils::Animate(option, [&]() { animateTouchHoverColor_->Set(color); }); 101 } 102 } 103 104 void InitializeParam(); 105 void PaintSwitch(RSCanvas& canvas, const OffsetF& contentOffset, const SizeF& contentSize); 106 void DrawTouchAndHoverBoard(RSCanvas& canvas, const OffsetF& offset) const; 107 float GetSwitchWidth(const SizeF& contentSize) const; 108 SetUserActiveColor(const Color & color)109 void SetUserActiveColor(const Color& color) 110 { 111 userActiveColor_ = color; 112 animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 113 } 114 SetPointColor(const Color & color)115 void SetPointColor(const Color& color) 116 { 117 animatePointColor_->Set(LinearColor(color)); 118 } 119 SetEnabled(bool enabled)120 void SetEnabled(bool enabled) 121 { 122 if (enabled_) { 123 enabled_->Set(enabled); 124 } 125 } 126 SetIsHover(bool isHover)127 void SetIsHover(bool isHover) 128 { 129 if (isHover_) { 130 isHover_->Set(isHover); 131 } 132 } 133 SetIsSelect(bool isSelect)134 void SetIsSelect(bool isSelect) 135 { 136 if (isSelect_) { 137 isSelect_->Set(isSelect); 138 } 139 } 140 SetHotZoneOffset(OffsetF & hotZoneOffset)141 void SetHotZoneOffset(OffsetF& hotZoneOffset) 142 { 143 hotZoneOffset_ = hotZoneOffset; 144 } 145 SetHotZoneSize(SizeF & hotZoneSize)146 void SetHotZoneSize(SizeF& hotZoneSize) 147 { 148 hotZoneSize_ = hotZoneSize; 149 } 150 SetOffset(OffsetF & offset)151 void SetOffset(OffsetF& offset) 152 { 153 if (offset_) { 154 offset_->Set(offset); 155 } 156 } 157 SetSize(SizeF & size)158 void SetSize(SizeF& size) 159 { 160 if (size_) { 161 size_->Set(size); 162 } 163 } 164 SetDragOffsetX(float dragOffsetX)165 void SetDragOffsetX(float dragOffsetX) 166 { 167 if (dragOffsetX_) { 168 dragOffsetX_->Set(dragOffsetX); 169 } 170 } 171 SetPointOffset(float pointOffset)172 void SetPointOffset(float pointOffset) 173 { 174 if (pointOffset_) { 175 pointOffset_->Set(pointOffset); 176 } 177 } 178 SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)179 void SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType) 180 { 181 touchHoverType_ = touchHoverType; 182 } 183 SetIsDragEvent(bool isDragEvent)184 void SetIsDragEvent(bool isDragEvent) 185 { 186 isDragEvent_ = isDragEvent; 187 } 188 189 private: 190 float actualWidth_ = 0.0f; 191 float actualHeight_ = 0.0f; 192 float pointRadius_ = 0.0f; 193 const Dimension radiusGap_ = 2.0_vp; 194 Color clickEffectColor_; 195 Color hoverColor_; 196 Color activeColor_; 197 Color inactiveColor_; 198 Color userActiveColor_; 199 Dimension hoverRadius_ = 8.0_vp; 200 float hoverDuration_ = 0.0f; 201 float hoverToTouchDuration_ = 0.0f; 202 float touchDuration_ = 0.0f; 203 float colorAnimationDuration_ = 0.0f; 204 float pointAnimationDuration_ = 0.0f; 205 bool isDragEvent_ = false; 206 bool isFirstCreated_ = true; 207 208 OffsetF hotZoneOffset_; 209 SizeF hotZoneSize_; 210 TouchHoverAnimationType touchHoverType_ = TouchHoverAnimationType::NONE; 211 212 RefPtr<AnimatablePropertyColor> animatableBoardColor_; 213 RefPtr<AnimatablePropertyColor> animateTouchHoverColor_; 214 RefPtr<AnimatablePropertyColor> animatePointColor_; 215 RefPtr<AnimatablePropertyFloat> pointOffset_; 216 RefPtr<PropertyFloat> dragOffsetX_; 217 RefPtr<PropertyBool> isSelect_; 218 RefPtr<PropertyBool> isHover_; 219 RefPtr<AnimatablePropertyOffsetF> offset_; 220 RefPtr<AnimatablePropertySizeF> size_; 221 RefPtr<PropertyBool> enabled_; 222 223 ACE_DISALLOW_COPY_AND_MOVE(SwitchModifier); 224 }; 225 } // namespace OHOS::Ace::NG 226 227 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H 228