mirror of
https://gitee.com/openharmony/arkui_ace_engine
synced 2024-11-23 07:01:24 +00:00
优化滚动类组件双指抛滑体验
Signed-off-by: shihongjie <shihongjie@huawei.com> Change-Id: I9a382124788199a6ffdf188386a11c62b1464689
This commit is contained in:
parent
baaab837eb
commit
a2a856e145
@ -95,7 +95,8 @@ const char* PATTERN_MAP[] = {
|
||||
THEME_BLUR_STYLE_COMMON,
|
||||
THEME_PATTERN_SHADOW,
|
||||
THEME_PATTERN_CONTAINER_MODAL,
|
||||
THEME_PATTERN_LINEAR_INDICATOR
|
||||
THEME_PATTERN_LINEAR_INDICATOR,
|
||||
THEME_PATTERN_SCROLLABLE
|
||||
};
|
||||
|
||||
bool IsDirExist(const std::string& path)
|
||||
|
@ -84,6 +84,7 @@ const char THEME_PATTERN_LINEAR_INDICATOR[] = "linear_indicator_pattern";
|
||||
const char THEME_BLUR_STYLE_COMMON[] = "blur_style_common";
|
||||
const char THEME_PATTERN_SHADOW[] = "shadow_pattern";
|
||||
const char THEME_PATTERN_CONTAINER_MODAL[] = "container_modal_pattern";
|
||||
const char THEME_PATTERN_SCROLLABLE[] = "scrollable_pattern";
|
||||
|
||||
// pattern general attributes
|
||||
const char PATTERN_FG_COLOR[] = "fg_color";
|
||||
|
@ -86,6 +86,7 @@ extern const char THEME_PATTERN_SHADOW[];
|
||||
extern const char THEME_PATTERN_CONTAINER_MODAL[];
|
||||
extern const char THEME_PATTERN_AGING_ADAPATION_DIALOG[];
|
||||
extern const char THEME_PATTERN_LINEAR_INDICATOR[];
|
||||
extern const char THEME_PATTERN_SCROLLABLE[];
|
||||
|
||||
// pattern general attributes
|
||||
extern const char PATTERN_FG_COLOR[];
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "core/components_ng/pattern/menu/menu_theme.h"
|
||||
#include "core/components_ng/pattern/rich_editor/rich_editor_theme.h"
|
||||
#include "core/components_ng/pattern/linear_indicator/linear_indicator_theme.h"
|
||||
#include "core/components_ng/pattern/scrollable/scrollable_theme.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
@ -145,6 +146,7 @@ const std::unordered_map<ThemeType, RefPtr<Theme>(*)(const RefPtr<ThemeConstants
|
||||
{ NG::ContainerModalTheme::TypeId(), &ThemeBuildFunc<NG::ContainerModalTheme::Builder> },
|
||||
{ AgingAdapationDialogTheme::TypeId(), &ThemeBuildFunc<AgingAdapationDialogTheme::Builder> },
|
||||
{ NG::LinearIndicatorTheme::TypeId(), &ThemeBuildFunc<NG::LinearIndicatorTheme::Builder> },
|
||||
{ NG::ScrollableTheme::TypeId(), &ThemeBuildFunc<NG::ScrollableTheme::Builder> },
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
@ -392,7 +392,7 @@ bool GridPattern::UpdateCurrentOffset(float offset, int32_t source)
|
||||
} else {
|
||||
overScroll = gridLayoutInfo_.currentOffset_ - (GetMainContentSize() - itemsHeight);
|
||||
}
|
||||
auto friction = ScrollablePattern::CalculateFriction(std::abs(overScroll) / GetMainContentSize());
|
||||
auto friction = CalculateFriction(std::abs(overScroll) / GetMainContentSize());
|
||||
offset *= friction;
|
||||
}
|
||||
auto userOffset = FireOnWillScroll(-offset);
|
||||
@ -408,8 +408,7 @@ bool GridPattern::UpdateCurrentOffset(float offset, int32_t source)
|
||||
}
|
||||
if (gridLayoutInfo_.reachStart_) {
|
||||
if (source == SCROLL_FROM_UPDATE) {
|
||||
auto friction =
|
||||
ScrollablePattern::CalculateFriction(std::abs(gridLayoutInfo_.currentOffset_) / GetMainContentSize());
|
||||
auto friction = CalculateFriction(std::abs(gridLayoutInfo_.currentOffset_) / GetMainContentSize());
|
||||
offset *= friction;
|
||||
}
|
||||
auto userOffset = FireOnWillScroll(-offset);
|
||||
|
@ -846,7 +846,7 @@ bool ListPattern::UpdateCurrentOffset(float offset, int32_t source)
|
||||
// over scroll in drag update from normal to over scroll.
|
||||
float overScroll = std::max(res.start, res.end);
|
||||
// adjust offset.
|
||||
auto friction = ScrollablePattern::CalculateFriction(std::abs(overScroll) / contentMainSize_);
|
||||
auto friction = CalculateFriction(std::abs(overScroll) / contentMainSize_);
|
||||
currentDelta_ = currentDelta_ * friction;
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,21 @@ float RefreshPattern::CalculatePullDownRatio()
|
||||
auto geometryNode = host->GetGeometryNode();
|
||||
CHECK_NULL_RETURN(geometryNode, 1.0f);
|
||||
auto contentHeight = geometryNode->GetPaddingSize().Height();
|
||||
return NearZero(contentHeight) ? 1.0f : ScrollablePattern::CalculateFriction(scrollOffset_ / contentHeight);
|
||||
if (NearZero(contentHeight)) {
|
||||
return 1.0f;
|
||||
}
|
||||
if (!ratio_.has_value()) {
|
||||
auto context = GetContext();
|
||||
CHECK_NULL_RETURN(context, 1.0f);
|
||||
auto scrollableTheme = context->GetTheme<ScrollableTheme>();
|
||||
CHECK_NULL_RETURN(scrollableTheme, 1.0f);
|
||||
ratio_ = scrollableTheme->GetRatio();
|
||||
}
|
||||
auto gamma = scrollOffset_ / contentHeight;
|
||||
if (GreatOrEqual(gamma, 1.0)) {
|
||||
gamma = 1.0f;
|
||||
}
|
||||
return exp(-ratio_.value() * gamma);
|
||||
}
|
||||
|
||||
float RefreshPattern::GetFollowRatio()
|
||||
|
@ -170,6 +170,7 @@ private:
|
||||
bool pullToRefresh_ = true;
|
||||
RefPtr<NodeAnimatablePropertyFloat> offsetProperty_;
|
||||
std::shared_ptr<AnimationUtils::Animation> animation_;
|
||||
std::optional<float> ratio_;
|
||||
// API version 10
|
||||
void InitLowVersionOffset();
|
||||
void UpdateChild();
|
||||
|
@ -305,7 +305,7 @@ void ScrollPattern::AdjustOffset(float& delta, int32_t source)
|
||||
if (overScrollPast == 0.0f) {
|
||||
return;
|
||||
}
|
||||
float friction = ScrollablePattern::CalculateFriction((overScrollPast - std::abs(delta)) / viewPortLength_);
|
||||
float friction = CalculateFriction((overScrollPast - std::abs(delta)) / viewPortLength_);
|
||||
float direction = delta > 0.0f ? 1.0f : -1.0f;
|
||||
delta = direction * CalculateOffsetByFriction(overScrollPast, std::abs(delta), friction);
|
||||
}
|
||||
|
@ -27,6 +27,16 @@ void ScrollSpringEffect::RegisterSpringCallback()
|
||||
effect->ProcessScrollOver(velocity);
|
||||
});
|
||||
scrollable_->SetCurrentPositionCallback(currentPositionCallback_);
|
||||
scrollable_->SetOverScrollOffsetCallback([weakEffect = AceType::WeakClaim(this)]() {
|
||||
auto effect = weakEffect.Upgrade();
|
||||
if (effect) {
|
||||
double position = effect->currentPositionCallback_();
|
||||
double minExtent = effect->leadingCallback_();
|
||||
double maxExtent = effect->trailingCallback_();
|
||||
return std::max(minExtent - position, position - maxExtent);
|
||||
}
|
||||
return 0.0;
|
||||
});
|
||||
}
|
||||
|
||||
void ScrollSpringEffect::InitialEdgeEffect()
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "base/log/jank_frame_report.h"
|
||||
#include "core/common/layout_inspector.h"
|
||||
#include "core/components_ng/pattern/scrollable/scrollable_theme.h"
|
||||
#include "core/pipeline_ng/pipeline_context.h"
|
||||
|
||||
namespace OHOS::Ace::NG {
|
||||
@ -83,30 +84,6 @@ void Scrollable::SetFriction(double sFriction)
|
||||
sFriction_ = sFriction;
|
||||
}
|
||||
|
||||
Scrollable::Scrollable()
|
||||
{
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction_;
|
||||
velocityScale_ =
|
||||
Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? NEW_VELOCITY_SCALE : VELOCITY_SCALE;
|
||||
}
|
||||
|
||||
Scrollable::Scrollable(ScrollPositionCallback&& callback, Axis axis) : callback_(std::move(callback)), axis_(axis)
|
||||
{
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction_;
|
||||
velocityScale_ =
|
||||
Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? NEW_VELOCITY_SCALE : VELOCITY_SCALE;
|
||||
}
|
||||
|
||||
Scrollable::Scrollable(const ScrollPositionCallback& callback, Axis axis) : callback_(callback), axis_(axis)
|
||||
{
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction_;
|
||||
velocityScale_ =
|
||||
Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? NEW_VELOCITY_SCALE : VELOCITY_SCALE;
|
||||
}
|
||||
|
||||
Scrollable::~Scrollable()
|
||||
{
|
||||
// If animation still runs, force stop it.
|
||||
@ -183,6 +160,23 @@ void Scrollable::Initialize(const WeakPtr<PipelineBase>& context)
|
||||
panRecognizerNG_->SetOnActionCancel(actionCancel);
|
||||
|
||||
available_ = true;
|
||||
|
||||
auto pipeline = context_.Upgrade();
|
||||
CHECK_NULL_VOID(pipeline);
|
||||
auto scrollableTheme = pipeline->GetTheme<ScrollableTheme>();
|
||||
CHECK_NULL_VOID(scrollableTheme);
|
||||
flingVelocityScale_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)
|
||||
? scrollableTheme->GetFlingVelocityScale()
|
||||
: VELOCITY_SCALE;
|
||||
springVelocityScale_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)
|
||||
? scrollableTheme->GetSpringVelocityScale()
|
||||
: VELOCITY_SCALE;
|
||||
ratio_ = scrollableTheme->GetRatio();
|
||||
springResponse_ = scrollableTheme->GetSpringResponse();
|
||||
touchPadVelocityScaleRate_ = scrollableTheme->GetTouchPadVelocityScaleRate();
|
||||
if (friction_ == -1) {
|
||||
InitFriction(scrollableTheme->GetFriction());
|
||||
}
|
||||
}
|
||||
|
||||
void Scrollable::SetAxis(Axis axis)
|
||||
@ -402,13 +396,16 @@ void Scrollable::HandleDragUpdate(const GestureEvent& info)
|
||||
HandleScroll(mainDelta, source, NestedState::GESTURE);
|
||||
}
|
||||
|
||||
void Scrollable::LayoutDirectionEst(double& correctVelocity)
|
||||
void Scrollable::LayoutDirectionEst(double gestureVelocity, double velocityScale, bool isScrollFromTouchPad)
|
||||
{
|
||||
sVelocityScale_ = isScrollFromTouchPad ? velocityScale * touchPadVelocityScaleRate_ : velocityScale;
|
||||
if (isReverseCallback_ && isReverseCallback_()) {
|
||||
correctVelocity = -correctVelocity * sVelocityScale_.value_or(velocityScale_) * GetGain(GetDragOffset());
|
||||
currentVelocity_ = -gestureVelocity * sVelocityScale_.value_or(velocityScale) * GetGain(GetDragOffset());
|
||||
} else {
|
||||
correctVelocity = correctVelocity * sVelocityScale_.value_or(velocityScale_) * GetGain(GetDragOffset());
|
||||
currentVelocity_ = gestureVelocity * sVelocityScale_.value_or(velocityScale) * GetGain(GetDragOffset());
|
||||
}
|
||||
// Apply max fling velocity limit, it must be calculated after all fling velocity gain.
|
||||
currentVelocity_ = std::clamp(currentVelocity_, -maxFlingVelocity_ + slipFactor_, maxFlingVelocity_ - slipFactor_);
|
||||
}
|
||||
|
||||
void Scrollable::HandleDragEnd(const GestureEvent& info)
|
||||
@ -421,24 +418,20 @@ void Scrollable::HandleDragEnd(const GestureEvent& info)
|
||||
if (dragFRCSceneCallback_) {
|
||||
dragFRCSceneCallback_(info.GetMainVelocity(), NG::SceneStatus::END);
|
||||
}
|
||||
bool isScrollFromTouchPad = info.GetSourceTool() == SourceTool::TOUCHPAD;
|
||||
isDragUpdateStop_ = false;
|
||||
touchUp_ = false;
|
||||
scrollPause_ = false;
|
||||
lastVelocity_ = GetPanDirection() == Axis::NONE ? 0.0 : info.GetMainVelocity();
|
||||
double gestureVelocity = GetPanDirection() == Axis::NONE ? 0.0 : info.GetMainVelocity();
|
||||
SetDragEndPosition(GetMainOffset(Offset(info.GetGlobalPoint().GetX(), info.GetGlobalPoint().GetY())));
|
||||
LayoutDirectionEst(gestureVelocity);
|
||||
// Apply max fling velocity limit, it must be calculated after all fling velocity gain.
|
||||
currentVelocity_ = std::clamp(gestureVelocity, -maxFlingVelocity_ + slipFactor_, maxFlingVelocity_ - slipFactor_);
|
||||
|
||||
lastPos_ = GetDragOffset();
|
||||
JankFrameReport::GetInstance().ClearFrameJankFlag(JANK_RUNNING_SCROLL);
|
||||
double mainPosition = GetMainOffset(Offset(info.GetGlobalPoint().GetX(), info.GetGlobalPoint().GetY()));
|
||||
mainPosition = Round(mainPosition);
|
||||
ACE_SCOPED_TRACE("HandleDragEnd, mainPosition:%f, gestureVelocity:%f, currentVelocity:%f, moved_:%u "
|
||||
"canOverScroll_:%u, id:%d, tag:%s",
|
||||
mainPosition, gestureVelocity, currentVelocity_, moved_, canOverScroll_, nodeId_, nodeTag_.c_str());
|
||||
if (!moved_ || IsMouseWheelScroll(info)) {
|
||||
LayoutDirectionEst(gestureVelocity, flingVelocityScale_, isScrollFromTouchPad);
|
||||
if (calcPredictSnapOffsetCallback_) {
|
||||
std::optional<float> predictSnapOffset = calcPredictSnapOffsetCallback_(0.0f, 0.0f, 0.0f);
|
||||
if (predictSnapOffset.has_value() && !NearZero(predictSnapOffset.value())) {
|
||||
@ -457,14 +450,23 @@ void Scrollable::HandleDragEnd(const GestureEvent& info)
|
||||
#endif
|
||||
} else if (!Container::IsCurrentUseNewPipeline() && outBoundaryCallback_ && outBoundaryCallback_() &&
|
||||
scrollOverCallback_) {
|
||||
LayoutDirectionEst(gestureVelocity, flingVelocityScale_, isScrollFromTouchPad);
|
||||
ResetContinueDragCount();
|
||||
ProcessScrollOverCallback(currentVelocity_);
|
||||
} else if (canOverScroll_) {
|
||||
LayoutDirectionEst(gestureVelocity, springVelocityScale_, isScrollFromTouchPad);
|
||||
auto gamma = overScrollOffsetCallback_() / continuousSlidingCallback_();
|
||||
gamma = GreatOrEqual(gamma, 1.0) ? 1.0f : gamma;
|
||||
currentVelocity_ = currentVelocity_ * exp(-ratio_ * gamma);
|
||||
ResetContinueDragCount();
|
||||
HandleOverScroll(currentVelocity_);
|
||||
} else {
|
||||
StartScrollAnimation(mainPosition, currentVelocity_);
|
||||
LayoutDirectionEst(gestureVelocity, flingVelocityScale_, isScrollFromTouchPad);
|
||||
StartScrollAnimation(mainPosition, currentVelocity_, isScrollFromTouchPad);
|
||||
}
|
||||
ACE_SCOPED_TRACE("HandleDragEnd, mainPosition:%f, gestureVelocity:%f, currentVelocity:%f, moved_:%u "
|
||||
"canOverScroll_:%u, id:%d, tag:%s",
|
||||
mainPosition, gestureVelocity, currentVelocity_, moved_, canOverScroll_, nodeId_, nodeTag_.c_str());
|
||||
SetDelayedTask();
|
||||
if (dragEndCallback_) {
|
||||
dragEndCallback_();
|
||||
@ -472,7 +474,7 @@ void Scrollable::HandleDragEnd(const GestureEvent& info)
|
||||
isTouching_ = false;
|
||||
}
|
||||
|
||||
void Scrollable::StartScrollAnimation(float mainPosition, float correctVelocity)
|
||||
void Scrollable::StartScrollAnimation(float mainPosition, float correctVelocity, bool isScrollFromTouchPad)
|
||||
{
|
||||
if (!isSpringAnimationStop_) {
|
||||
StopSpringAnimation();
|
||||
@ -501,7 +503,9 @@ void Scrollable::StartScrollAnimation(float mainPosition, float correctVelocity)
|
||||
currentVelocity_ = 0.0;
|
||||
return;
|
||||
}
|
||||
if (NearZero(correctVelocity, FRICTION_VELOCITY_THRESHOLD)) {
|
||||
auto frictionVelocityTh = isScrollFromTouchPad ? FRICTION_VELOCITY_THRESHOLD * touchPadVelocityScaleRate_
|
||||
: FRICTION_VELOCITY_THRESHOLD;
|
||||
if (NearZero(correctVelocity, frictionVelocityTh)) {
|
||||
HandleScrollEnd(correctVelocity);
|
||||
currentVelocity_ = 0.0;
|
||||
#ifdef OHOS_PLATFORM
|
||||
@ -638,6 +642,13 @@ float Scrollable::GetFrictionVelocityByFinalPosition(float final, float position
|
||||
return DEFAULT_THRESHOLD * threshold * signum - (final - position) * friction;
|
||||
}
|
||||
|
||||
void Scrollable::InitFriction(double friction)
|
||||
{
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction_;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_THIRTEEN) ? friction : friction_;
|
||||
}
|
||||
|
||||
void Scrollable::FixScrollMotion(float position, float initVelocity)
|
||||
{
|
||||
#ifdef WEARABLE_PRODUCT
|
||||
@ -815,7 +826,7 @@ void Scrollable::StartSpringMotion(
|
||||
springAnimationCount_++;
|
||||
springOffsetProperty_->Set(mainPosition);
|
||||
AnimationOption option;
|
||||
auto curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(DEFAULT_SPRING_RESPONSE, DEFAULT_SPRING_DAMP, 0.0f);
|
||||
auto curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(springResponse_, DEFAULT_SPRING_DAMP, 0.0f);
|
||||
option.SetCurve(curve);
|
||||
option.SetDuration(CUSTOM_SPRING_ANIMATION_DURATION);
|
||||
springOffsetProperty_->SetPropertyUnit(PropertyUnit::PIXEL_POSITION);
|
||||
|
@ -74,9 +74,9 @@ class Scrollable : public TouchEventTarget {
|
||||
DECLARE_ACE_TYPE(Scrollable, TouchEventTarget);
|
||||
|
||||
public:
|
||||
Scrollable();
|
||||
Scrollable(ScrollPositionCallback&& callback, Axis axis);
|
||||
Scrollable(const ScrollPositionCallback& callback, Axis axis);
|
||||
Scrollable() = default;
|
||||
Scrollable(ScrollPositionCallback&& callback, Axis axis) : callback_(std::move(callback)), axis_(axis) {}
|
||||
Scrollable(const ScrollPositionCallback& callback, Axis axis) : callback_(callback), axis_(axis) {}
|
||||
~Scrollable() override;
|
||||
|
||||
static void SetVelocityScale(double sVelocityScale);
|
||||
@ -160,7 +160,7 @@ public:
|
||||
void HandleScrollEnd(const std::optional<float>& velocity);
|
||||
bool HandleOverScroll(double velocity);
|
||||
ScrollResult HandleScroll(double offset, int32_t source, NestedState state);
|
||||
void LayoutDirectionEst(double& correctVelocity);
|
||||
void LayoutDirectionEst(double correctVelocity, double velocityScale, bool isScrollFromTouchPad);
|
||||
|
||||
void SetMoved(bool value)
|
||||
{
|
||||
@ -337,7 +337,7 @@ public:
|
||||
{
|
||||
overScrollCallback_ = std::move(func);
|
||||
}
|
||||
void StartScrollAnimation(float mainPosition, float velocity);
|
||||
void StartScrollAnimation(float mainPosition, float velocity, bool isScrollFromTouchPad = false);
|
||||
void SetOnScrollStartRec(std::function<void(float)>&& func)
|
||||
{
|
||||
onScrollStartRec_ = std::move(func);
|
||||
@ -470,6 +470,11 @@ public:
|
||||
return nestedScrolling_;
|
||||
}
|
||||
|
||||
void SetOverScrollOffsetCallback(std::function<double()> overScrollOffsetCallback)
|
||||
{
|
||||
overScrollOffsetCallback_ = overScrollOffsetCallback;
|
||||
}
|
||||
|
||||
private:
|
||||
bool UpdateScrollPosition(double offset, int32_t source) const;
|
||||
void ProcessSpringMotion(double position);
|
||||
@ -483,6 +488,7 @@ private:
|
||||
void MarkNeedFlushAnimationStartTime();
|
||||
float GetFrictionVelocityByFinalPosition(
|
||||
float final, float position, float signum, float friction, float threshold = DEFAULT_MULTIPLIER);
|
||||
void InitFriction(double friction);
|
||||
|
||||
/**
|
||||
* @brief Checks if the scroll event is caused by a mouse wheel.
|
||||
@ -540,7 +546,6 @@ private:
|
||||
double dragEndPosition_ = 0.0;
|
||||
double lastVelocity_ = 0.0;
|
||||
double friction_ = -1.0;
|
||||
double velocityScale_ = 0.0;
|
||||
double preGain_ = 1.0;
|
||||
#ifdef OHOS_PLATFORM
|
||||
int64_t startIncreaseTime_ = 0;
|
||||
@ -581,6 +586,12 @@ private:
|
||||
bool skipRestartSpring_ = false; // set to true when need to skip repeated spring animation
|
||||
uint32_t updateSnapAnimationCount_ = 0;
|
||||
uint32_t springAnimationCount_ = 0;
|
||||
double flingVelocityScale_ = 1.5;
|
||||
double springVelocityScale_ = 1.5;
|
||||
float ratio_ = 1.848f;
|
||||
float springResponse_ = 0.416f;
|
||||
float touchPadVelocityScaleRate_ = 1.0f;
|
||||
std::function<double()> overScrollOffsetCallback_;
|
||||
|
||||
RefPtr<NodeAnimatablePropertyFloat> snapOffsetProperty_;
|
||||
bool isSnapAnimationStop_ = true;
|
||||
|
@ -57,19 +57,6 @@ const std::string CUSTOM_SCROLL_BAR_SCENE = "custom_scroll_bar_scene";
|
||||
using std::chrono::high_resolution_clock;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
ScrollablePattern::ScrollablePattern()
|
||||
{
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction_;
|
||||
}
|
||||
|
||||
ScrollablePattern::ScrollablePattern(EdgeEffect edgeEffect, bool alwaysEnabled)
|
||||
: edgeEffect_(edgeEffect), edgeEffectAlwaysEnabled_(alwaysEnabled)
|
||||
{
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction_;
|
||||
}
|
||||
|
||||
RefPtr<PaintProperty> ScrollablePattern::CreatePaintProperty()
|
||||
{
|
||||
auto defaultDisplayMode = GetDefaultScrollBarDisplayMode();
|
||||
@ -513,6 +500,14 @@ void ScrollablePattern::AddScrollEvent()
|
||||
scrollable->SetNodeId(host->GetAccessibilityId());
|
||||
scrollable->SetNodeTag(host->GetTag());
|
||||
scrollable->Initialize(host->GetContextRefPtr());
|
||||
if (!ratio_.has_value()) {
|
||||
auto context = GetContext();
|
||||
CHECK_NULL_VOID(context);
|
||||
auto scrollableTheme = context->GetTheme<ScrollableTheme>();
|
||||
CHECK_NULL_VOID(scrollableTheme);
|
||||
ratio_ = scrollableTheme->GetRatio();
|
||||
}
|
||||
|
||||
AttachAnimatableProperty(scrollable);
|
||||
|
||||
// move HandleScroll and HandleOverScroll to ScrollablePattern by setting callbacks to scrollable
|
||||
@ -579,7 +574,6 @@ void ScrollablePattern::AddScrollEvent()
|
||||
};
|
||||
scrollable->SetDragEndCallback(std::move(dragEnd));
|
||||
|
||||
scrollable->SetUnstaticFriction(friction_);
|
||||
scrollable->SetMaxFlingVelocity(maxFlingVelocity_);
|
||||
|
||||
auto scrollSnap = [weak = WeakClaim(this)](double targetOffset, double velocity) -> bool {
|
||||
@ -1088,6 +1082,12 @@ void ScrollablePattern::SetFriction(double friction)
|
||||
Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN) ? API11_FRICTION : FRICTION;
|
||||
friction =
|
||||
Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) ? API12_FRICTION : friction;
|
||||
if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_THIRTEEN)) {
|
||||
auto context = GetContext();
|
||||
CHECK_NULL_VOID(context);
|
||||
auto scrollableTheme = context->GetTheme<ScrollableTheme>();
|
||||
friction = scrollableTheme->GetFriction();
|
||||
}
|
||||
}
|
||||
friction_ = friction;
|
||||
CHECK_NULL_VOID(scrollableEvent_);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "core/components_ng/pattern/scrollable/scrollable_paint_method.h"
|
||||
#include "core/components_ng/pattern/scrollable/scrollable_paint_property.h"
|
||||
#include "core/components_ng/pattern/scrollable/scrollable_properties.h"
|
||||
#include "core/components_ng/pattern/scrollable/scrollable_theme.h"
|
||||
#include "core/components_ng/render/animation_utils.h"
|
||||
#include "core/event/mouse_event.h"
|
||||
#include "core/components_ng/event/scrollable_event.h"
|
||||
@ -62,8 +63,10 @@ class ScrollablePattern : public NestableScrollContainer {
|
||||
DECLARE_ACE_TYPE(ScrollablePattern, NestableScrollContainer);
|
||||
|
||||
public:
|
||||
ScrollablePattern();
|
||||
ScrollablePattern(EdgeEffect edgeEffect, bool alwaysEnabled);
|
||||
ScrollablePattern() = default;
|
||||
ScrollablePattern(EdgeEffect edgeEffect, bool alwaysEnabled)
|
||||
: edgeEffect_(edgeEffect), edgeEffectAlwaysEnabled_(alwaysEnabled)
|
||||
{}
|
||||
|
||||
~ScrollablePattern()
|
||||
{
|
||||
@ -421,13 +424,12 @@ public:
|
||||
|
||||
static ScrollSource ConvertScrollSource(int32_t source);
|
||||
|
||||
static float CalculateFriction(float gamma)
|
||||
float CalculateFriction(float gamma)
|
||||
{
|
||||
constexpr float RATIO = 1.848f;
|
||||
if (GreatOrEqual(gamma, 1.0)) {
|
||||
gamma = 1.0f;
|
||||
}
|
||||
return exp(-RATIO * gamma);
|
||||
return exp(-ratio_.value_or(1.848f) * gamma);
|
||||
}
|
||||
virtual float GetMainContentSize() const;
|
||||
|
||||
@ -881,7 +883,8 @@ private:
|
||||
bool isSheetInReactive_ = false;
|
||||
bool isCoordEventNeedSpring_ = true;
|
||||
double scrollBarOutBoundaryExtent_ = 0.0;
|
||||
double friction_ = 0.0;
|
||||
std::optional<float> ratio_;
|
||||
double friction_ = -1.0;
|
||||
double maxFlingVelocity_ = MAX_VELOCITY;
|
||||
// scroller
|
||||
RefPtr<Animator> animator_;
|
||||
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLLABLE_SCROLLABLE_THEME_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLLABLE_SCROLLABLE_THEME_H
|
||||
|
||||
#include "core/components/theme/theme.h"
|
||||
#include "core/components/theme/theme_constants.h"
|
||||
#include "core/components/theme/theme_constants_defines.h"
|
||||
|
||||
namespace OHOS::Ace::NG {
|
||||
|
||||
class ScrollableTheme : public virtual Theme {
|
||||
DECLARE_ACE_TYPE(ScrollableTheme, Theme);
|
||||
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
Builder() = default;
|
||||
~Builder() = default;
|
||||
|
||||
RefPtr<ScrollableTheme> Build(const RefPtr<ThemeConstants>& themeConstants) const
|
||||
{
|
||||
RefPtr<ScrollableTheme> theme = AceType::Claim(new ScrollableTheme());
|
||||
if (!themeConstants) {
|
||||
return theme;
|
||||
}
|
||||
ParsePattern(themeConstants, theme);
|
||||
return theme;
|
||||
}
|
||||
|
||||
private:
|
||||
void ParsePattern(const RefPtr<ThemeConstants>& themeConstants, const RefPtr<ScrollableTheme>& theme) const
|
||||
{
|
||||
if (!theme) {
|
||||
return;
|
||||
}
|
||||
RefPtr<ThemeStyle> pattern = themeConstants->GetPatternByName(THEME_PATTERN_SCROLLABLE);
|
||||
if (!pattern) {
|
||||
return;
|
||||
}
|
||||
theme->friction_ = pattern->GetAttr<double>("scroll_able_friction", 0.75f);
|
||||
theme->flingVelocityScale_ = pattern->GetAttr<double>("scroll_able_fling_velocity_scale", 1.5f);
|
||||
theme->springVelocityScale_ = pattern->GetAttr<double>("scroll_able_spring_velocity_scale", 1.5f);
|
||||
theme->ratio_ = pattern->GetAttr<double>("scroll_able_over_edge_following_ratio", 1.848f);
|
||||
theme->springResponse_ = pattern->GetAttr<double>("scroll_able_spring_response", 0.417f);
|
||||
theme->touchPadVelocityScaleRate_ =
|
||||
pattern->GetAttr<double>("scroll_able_touch_pad_velocity_scale_rate", 1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
~ScrollableTheme() override = default;
|
||||
|
||||
float GetFriction() const
|
||||
{
|
||||
return friction_;
|
||||
}
|
||||
|
||||
float GetFlingVelocityScale() const
|
||||
{
|
||||
return flingVelocityScale_;
|
||||
}
|
||||
|
||||
float GetSpringVelocityScale() const
|
||||
{
|
||||
return springVelocityScale_;
|
||||
}
|
||||
|
||||
float GetRatio() const
|
||||
{
|
||||
return ratio_;
|
||||
}
|
||||
|
||||
float GetSpringResponse() const
|
||||
{
|
||||
return springResponse_;
|
||||
}
|
||||
|
||||
float GetTouchPadVelocityScaleRate() const
|
||||
{
|
||||
return touchPadVelocityScaleRate_;
|
||||
}
|
||||
|
||||
protected:
|
||||
ScrollableTheme() = default;
|
||||
|
||||
private:
|
||||
float friction_ = 0.75f;
|
||||
float flingVelocityScale_ = 1.5f;
|
||||
float springVelocityScale_ = 1.5f;
|
||||
float ratio_ = 1.848f;
|
||||
float springResponse_ = 0.416f;
|
||||
float touchPadVelocityScaleRate_ = 1.0f;
|
||||
};
|
||||
} // namespace OHOS::Ace::NG
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SCROLLABLE_SCROLLABLE_THEME_H
|
@ -54,7 +54,7 @@ bool WaterFlowPattern::UpdateCurrentOffset(float delta, int32_t source)
|
||||
// over scroll in drag update from normal to over scroll.
|
||||
float overScroll = layoutInfo_->CalcOverScroll(GetMainContentSize(), delta);
|
||||
if (source == SCROLL_FROM_UPDATE) {
|
||||
auto friction = ScrollablePattern::CalculateFriction(std::abs(overScroll) / GetMainContentSize());
|
||||
auto friction = CalculateFriction(std::abs(overScroll) / GetMainContentSize());
|
||||
delta *= friction;
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user