已合并
新增nestedScroll接口,web适配嵌套滚动父组件优先 #21217
zhufenghao创建于 2023年11月2日
新增nestedScroll接口,web适配嵌套滚动父组件优先 #21217
已合并
从refs/pull/21217/head合入到master
共 11 个文件变更+125-5
| @@ -1640,6 +1640,7 @@ void JSWeb::JSBind(BindingTarget globalObj) | |||
| 1640 | JSClass<JSWeb>::StaticMethod("onOverScroll", &JSWeb::OnOverScroll); | 1640 | JSClass<JSWeb>::StaticMethod("onOverScroll", &JSWeb::OnOverScroll); |
| 1641 | JSClass<JSWeb>::StaticMethod("onScreenCaptureRequest", &JSWeb::OnScreenCaptureRequest); | 1641 | JSClass<JSWeb>::StaticMethod("onScreenCaptureRequest", &JSWeb::OnScreenCaptureRequest); |
| 1642 | JSClass<JSWeb>::StaticMethod("wrapContent", &JSWeb::WrapContent); | 1642 | JSClass<JSWeb>::StaticMethod("wrapContent", &JSWeb::WrapContent); |
| 1643 | + JSClass<JSWeb>::StaticMethod("nestedScroll", &JSWeb::SetNestedScroll); | ||
| 1643 | JSClass<JSWeb>::InheritAndBind<JSViewAbstract>(globalObj); | 1644 | JSClass<JSWeb>::InheritAndBind<JSViewAbstract>(globalObj); |
| 1644 | JSWebDialog::JSBind(globalObj); | 1645 | JSWebDialog::JSBind(globalObj); |
| 1645 | JSWebGeolocation::JSBind(globalObj); | 1646 | JSWebGeolocation::JSBind(globalObj); |
| @@ -3574,4 +3575,33 @@ void JSWeb::WrapContent(bool isWrapContentEnabled) | |||
| 3574 | { | 3575 | { |
| 3575 | WebModel::GetInstance()->SetWrapContent(isWrapContentEnabled); | 3576 | WebModel::GetInstance()->SetWrapContent(isWrapContentEnabled); |
| 3576 | } | 3577 | } |
| 3578 | + | ||
| 3579 | +void JSWeb::SetNestedScroll(const JSCallbackInfo& args) | ||
| 3580 | +{ | ||
| 3581 | + NestedScrollOptions nestedOpt = { | ||
| 3582 | + .forward = NestedScrollMode::SELF_ONLY, | ||
| 3583 | + .backward = NestedScrollMode::SELF_ONLY, | ||
| 3584 | + }; | ||
| 3585 | + if (args.Length() < 1 || !args[0]->IsObject()) { | ||
| 3586 | + WebModel::GetInstance()->SetNestedScroll(nestedOpt); | ||
| 3587 | + return; | ||
| 3588 | + } | ||
| 3589 | + JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]); | ||
| 3590 | + int32_t froward = 0; | ||
| 3591 | + JSViewAbstract::ParseJsInt32(obj->GetProperty("scrollForward"), froward); | ||
| 3592 | + if (froward < static_cast<int32_t>(NestedScrollMode::SELF_ONLY) || | ||
| 3593 | + froward > static_cast<int32_t>(NestedScrollMode::PARALLEL)) { | ||
| 3594 | + froward = 0; | ||
| 3595 | + } | ||
| 3596 | + int32_t backward = 0; | ||
| 3597 | + JSViewAbstract::ParseJsInt32(obj->GetProperty("scrollBackward"), backward); | ||
| 3598 | + if (backward < static_cast<int32_t>(NestedScrollMode::SELF_ONLY) || | ||
| 3599 | + backward > static_cast<int32_t>(NestedScrollMode::PARALLEL)) { | ||
| 3600 | + backward = 0; | ||
| 3601 | + } | ||
| 3602 | + nestedOpt.forward = static_cast<NestedScrollMode>(froward); | ||
| 3603 | + nestedOpt.backward = static_cast<NestedScrollMode>(backward); | ||
| 3604 | + WebModel::GetInstance()->SetNestedScroll(nestedOpt); | ||
| 3605 | + args.ReturnSelf(); | ||
| 3606 | +} | ||
| 3577 | } // namespace OHOS::Ace::Framework | 3607 | } // namespace OHOS::Ace::Framework |
| @@ -129,6 +129,7 @@ public: | |||
| 129 | static void OnControllerAttached(const JSCallbackInfo& args); | 129 | static void OnControllerAttached(const JSCallbackInfo& args); |
| 130 | static void OnOverScroll(const JSCallbackInfo& args); | 130 | static void OnOverScroll(const JSCallbackInfo& args); |
| 131 | static void WrapContent(bool isWrapContentEnabled); | 131 | static void WrapContent(bool isWrapContentEnabled); |
| 132 | + static void SetNestedScroll(const JSCallbackInfo& info); | ||
| 132 | // Enable or disable debugging of web content | 133 | // Enable or disable debugging of web content |
| 133 | static bool webDebuggingAccess_; | 134 | static bool webDebuggingAccess_; |
| 134 | static JSwebEventCallback OnControllerAttachedCallback_; | 135 | static JSwebEventCallback OnControllerAttachedCallback_; |
| @@ -848,4 +848,12 @@ void WebClientImpl::OnRootLayerChanged(int width, int height) | |||
| 848 | CHECK_NULL_VOID(delegate); | 848 | CHECK_NULL_VOID(delegate); |
| 849 | delegate->OnRootLayerChanged(width, height); | 849 | delegate->OnRootLayerChanged(width, height); |
| 850 | } | 850 | } |
| 851 | + | ||
| 852 | +bool WebClientImpl::FilterScrollEvent(const float x, const float y, const float xVelocity, const float yVelocity) | ||
| 853 | +{ | ||
| 854 | + ContainerScope scope(instanceId_); | ||
| 855 | + auto delegate = webDelegate_.Upgrade(); | ||
| 856 | + CHECK_NULL_RETURN(delegate, false); | ||
| 857 | + return delegate->FilterScrollEvent(x, y, xVelocity, yVelocity); | ||
| 858 | +} | ||
| 851 | } // namespace OHOS::Ace | 859 | } // namespace OHOS::Ace |
| @@ -192,6 +192,7 @@ public: | |||
| 192 | void OnOverScrollFlingEnd() override; | 192 | void OnOverScrollFlingEnd() override; |
| 193 | void OnScrollState(bool scrollState) override; | 193 | void OnScrollState(bool scrollState) override; |
| 194 | void OnRootLayerChanged(int width, int height) override; | 194 | void OnRootLayerChanged(int width, int height) override; |
| 195 | + bool FilterScrollEvent(const float x, const float y, const float xVelocity, const float yVelocity) override; | ||
| 195 | 196 | ||
| 196 | void SetWebDelegate(const WeakPtr<WebDelegate>& delegate) | 197 | void SetWebDelegate(const WeakPtr<WebDelegate>& delegate) |
| 197 | { | 198 | { |
| @@ -5431,4 +5431,17 @@ bool WebDelegate::ShouldVirtualKeyboardOverlay() | |||
| 5431 | } | 5431 | } |
| 5432 | return false; | 5432 | return false; |
| 5433 | } | 5433 | } |
| 5434 | + | ||
| 5435 | +bool WebDelegate::FilterScrollEvent(const float x, const float y, const float xVelocity, const float yVelocity) | ||
| 5436 | +{ | ||
| 5437 | + auto webPattern = webPattern_.Upgrade(); | ||
| 5438 | + CHECK_NULL_RETURN(webPattern, false); | ||
| 5439 | + return webPattern->FilterScrollEvent(x, y, xVelocity, yVelocity); | ||
| 5440 | +} | ||
| 5441 | + | ||
| 5442 | +void WebDelegate::ScrollBy(float deltaX, float deltaY) | ||
| 5443 | +{ | ||
| 5444 | + CHECK_NULL_VOID(nweb_); | ||
| 5445 | + nweb_->ScrollBy(deltaX, deltaY); | ||
| 5446 | +} | ||
| 5434 | } // namespace OHOS::Ace | 5447 | } // namespace OHOS::Ace |
| @@ -598,6 +598,7 @@ public: | |||
| 598 | void OnOverScrollFlingVelocity(float xVelocity, float yVelocity, bool isFling); | 598 | void OnOverScrollFlingVelocity(float xVelocity, float yVelocity, bool isFling); |
| 599 | void OnScrollState(bool scrollState); | 599 | void OnScrollState(bool scrollState); |
| 600 | void OnRootLayerChanged(int width, int height); | 600 | void OnRootLayerChanged(int width, int height); |
| 601 | + bool FilterScrollEvent(const float x, const float y, const float xVelocity, const float yVelocity); | ||
| 601 | 602 | ||
| 602 | void SetNGWebPattern(const RefPtr<NG::WebPattern>& webPattern); | 603 | void SetNGWebPattern(const RefPtr<NG::WebPattern>& webPattern); |
| 603 | void RequestFocus(); | 604 | void RequestFocus(); |
| @@ -635,6 +636,7 @@ public: | |||
| 635 | void SetToken(); | 636 | void SetToken(); |
| 636 | void SetVirtualKeyBoardArg(int32_t width, int32_t height, double keyboard); | 637 | void SetVirtualKeyBoardArg(int32_t width, int32_t height, double keyboard); |
| 637 | bool ShouldVirtualKeyboardOverlay(); | 638 | bool ShouldVirtualKeyboardOverlay(); |
| 639 | + void ScrollBy(float deltaX, float deltaY); | ||
| 638 | private: | 640 | private: |
| 639 | void InitWebEvent(); | 641 | void InitWebEvent(); |
| 640 | void RegisterWebEvent(); | 642 | void RegisterWebEvent(); |
| @@ -140,7 +140,8 @@ public: | |||
| 140 | virtual void SetOverScrollId(std::function<void(const BaseEventInfo* info)>&& jsCallback) = 0; | 140 | virtual void SetOverScrollId(std::function<void(const BaseEventInfo* info)>&& jsCallback) = 0; |
| 141 | 141 | ||
| 142 | virtual void SetScreenCaptureRequestEventId(std::function<void(const BaseEventInfo* info)>&& jsCallback) {}; | 142 | virtual void SetScreenCaptureRequestEventId(std::function<void(const BaseEventInfo* info)>&& jsCallback) {}; |
| 143 | - virtual void SetWrapContent(bool isWrapContentEnabled) {}; | 143 | + virtual void SetWrapContent(bool isWrapContentEnabled) {} |
| 144 | + virtual void SetNestedScroll(const NestedScrollOptions& nestedOpt) {} | ||
| 144 | 145 | ||
| 145 | private: | 146 | private: |
| 146 | static std::unique_ptr<WebModel> instance_; | 147 | static std::unique_ptr<WebModel> instance_; |
| @@ -847,4 +847,11 @@ void WebModelNG::SetWrapContent(bool isWrapContentEnabled) | |||
| 847 | CHECK_NULL_VOID(webPattern); | 847 | CHECK_NULL_VOID(webPattern); |
| 848 | webPattern->SetWrapContent(isWrapContentEnabled); | 848 | webPattern->SetWrapContent(isWrapContentEnabled); |
| 849 | } | 849 | } |
| 850 | + | ||
| 851 | +void WebModelNG::SetNestedScroll(const NestedScrollOptions& nestedOpt) | ||
| 852 | +{ | ||
| 853 | + auto webPattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<WebPattern>(); | ||
| 854 | + CHECK_NULL_VOID(webPattern); | ||
| 855 | + webPattern->SetNestedScroll(nestedOpt); | ||
| 856 | +} | ||
| 850 | } // namespace OHOS::Ace::NG | 857 | } // namespace OHOS::Ace::NG |
| @@ -143,6 +143,7 @@ public: | |||
| 143 | void SetAudioExclusive(bool audioExclusive) override; | 143 | void SetAudioExclusive(bool audioExclusive) override; |
| 144 | void SetOverScrollId(std::function<void(const BaseEventInfo* info)>&& jsCallback) override; | 144 | void SetOverScrollId(std::function<void(const BaseEventInfo* info)>&& jsCallback) override; |
| 145 | void SetWrapContent(bool isWrapContentEnabled) override; | 145 | void SetWrapContent(bool isWrapContentEnabled) override; |
| 146 | + void SetNestedScroll(const NestedScrollOptions& nestedOpt) override; | ||
| 146 | }; | 147 | }; |
| 147 | } // namespace OHOS::Ace::NG | 148 | } // namespace OHOS::Ace::NG |
| 148 | 149 | ||
| @@ -2446,18 +2446,24 @@ void WebPattern::OnScrollEndRecursive() | |||
| 2446 | void WebPattern::OnOverScrollFlingVelocity(float xVelocity, float yVelocity, bool isFling) | 2446 | void WebPattern::OnOverScrollFlingVelocity(float xVelocity, float yVelocity, bool isFling) |
| 2447 | { | 2447 | { |
| 2448 | float velocity = GetAxis() == Axis::HORIZONTAL ? xVelocity : yVelocity; | 2448 | float velocity = GetAxis() == Axis::HORIZONTAL ? xVelocity : yVelocity; |
| 2449 | + if (nestedScrollMode_ != NestedScrollMode::SELF_FIRST) { | ||
| 2450 | + return; | ||
| 2451 | + } | ||
| 2449 | if (isFling) { | 2452 | if (isFling) { |
| 2450 | - if (isFirstFlingScrollVelocity_) { | 2453 | + if (velocity != 0 && isFirstFlingScrollVelocity_) { |
| 2451 | HandleScrollVelocity(velocity); | 2454 | HandleScrollVelocity(velocity); |
| 2452 | isFirstFlingScrollVelocity_ = false; | 2455 | isFirstFlingScrollVelocity_ = false; |
| 2453 | } | 2456 | } |
| 2454 | } else { | 2457 | } else { |
| 2455 | - HandleScroll(-velocity, SCROLL_FROM_UPDATE, NestedState::CHILD_SCROLL); | 2458 | + if (scrollState_) { |
| 2459 | + HandleScroll(-velocity, SCROLL_FROM_UPDATE, NestedState::CHILD_SCROLL); | ||
| 2460 | + } | ||
| 2456 | } | 2461 | } |
| 2457 | } | 2462 | } |
| 2458 | 2463 | ||
| 2459 | void WebPattern::OnScrollState(bool scrollState) | 2464 | void WebPattern::OnScrollState(bool scrollState) |
| 2460 | { | 2465 | { |
| 2466 | + scrollState_ = scrollState; | ||
| 2461 | if (!scrollState) { | 2467 | if (!scrollState) { |
| 2462 | OnScrollEndRecursive(); | 2468 | OnScrollEndRecursive(); |
| 2463 | } | 2469 | } |
| @@ -2468,7 +2474,8 @@ Axis WebPattern::GetParentAxis() | |||
| 2468 | auto parent = WebSearchParent(); | 2474 | auto parent = WebSearchParent(); |
| 2469 | parent_ = parent; | 2475 | parent_ = parent; |
| 2470 | CHECK_NULL_RETURN(parent, Axis::HORIZONTAL); | 2476 | CHECK_NULL_RETURN(parent, Axis::HORIZONTAL); |
| 2471 | - return parent->GetAxis(); | 2477 | + axis_ = parent->GetAxis(); |
| 2478 | + return axis_; | ||
| 2472 | } | 2479 | } |
| 2473 | 2480 | ||
| 2474 | RefPtr<NestableScrollContainer> WebPattern::WebSearchParent() | 2481 | RefPtr<NestableScrollContainer> WebPattern::WebSearchParent() |
| @@ -2497,4 +2504,48 @@ void WebPattern::OnRootLayerChanged(int width, int height) | |||
| 2497 | CHECK_NULL_VOID(frameNode); | 2504 | CHECK_NULL_VOID(frameNode); |
| 2498 | frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); | 2505 | frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); |
| 2499 | } | 2506 | } |
| 2507 | + | ||
| 2508 | +void WebPattern::SetNestedScroll(const NestedScrollOptions& nestedOpt) | ||
| 2509 | +{ | ||
| 2510 | + if (nestedOpt.forward == NestedScrollMode::SELF_ONLY && | ||
| 2511 | + nestedOpt.backward == NestedScrollMode::SELF_ONLY) { | ||
| 2512 | + nestedScrollMode_ = NestedScrollMode::SELF_ONLY; | ||
| 2513 | + } else if (nestedOpt.forward == NestedScrollMode::SELF_FIRST && | ||
| 2514 | + nestedOpt.backward == NestedScrollMode::SELF_FIRST) { | ||
| 2515 | + nestedScrollMode_ = NestedScrollMode::SELF_FIRST; | ||
| 2516 | + } else if (nestedOpt.forward == NestedScrollMode::PARENT_FIRST && | ||
| 2517 | + nestedOpt.backward == NestedScrollMode::PARENT_FIRST) { | ||
| 2518 | + nestedScrollMode_ = NestedScrollMode::PARENT_FIRST; | ||
| 2519 | + } else if (nestedOpt.forward == NestedScrollMode::PARALLEL && | ||
| 2520 | + nestedOpt.backward == NestedScrollMode::PARALLEL) { | ||
| 2521 | + nestedScrollMode_ = NestedScrollMode::PARALLEL; | ||
| 2522 | + } | ||
| 2523 | + TAG_LOGD(AceLogTag::ACE_WEB, "SetNestedScroll %{public}d", nestedScrollMode_); | ||
如果没有forward和backward不一样的情况,是不是只要判断一个就可以了 ![]() ![]()
不一样默认SELF_ONLY,先这样判断吧,只判断一个感觉不太合理。 ![]() ![]() | |||
| 2524 | +} | ||
| 2525 | + | ||
| 2526 | +bool WebPattern::FilterScrollEvent(const float x, const float y, const float xVelocity, const float yVelocity) | ||
| 2527 | +{ | ||
| 2528 | + float offset = GetAxis() == Axis::HORIZONTAL ? x : y; | ||
| 2529 | + float velocity = GetAxis() == Axis::HORIZONTAL ? xVelocity : yVelocity; | ||
| 2530 | + if (nestedScrollMode_ == NestedScrollMode::PARENT_FIRST) { | ||
| 2531 | + if (offset != 0) { | ||
| 2532 | + auto result = HandleScroll(offset, SCROLL_FROM_UPDATE, NestedState::CHILD_SCROLL); | ||
| 2533 | + float remainOffset = result.remain; | ||
| 2534 | + CHECK_NULL_RETURN(delegate_, true); | ||
| 2535 | + TAG_LOGD(AceLogTag::ACE_WEB, "FilterScrollEvent ScrollBy remainOffset = %{public}f", remainOffset); | ||
| 2536 | + GetAxis() == Axis::HORIZONTAL ? delegate_->ScrollBy(-remainOffset, 0) | ||
| 2537 | + : delegate_->ScrollBy(0, -remainOffset); | ||
| 2538 | + } else { | ||
| 2539 | + HandleScrollVelocity(velocity); | ||
| 2540 | + } | ||
| 2541 | + return true; | ||
| 2542 | + } else if (nestedScrollMode_ == NestedScrollMode::PARALLEL) { | ||
| 2543 | + if (offset != 0) { | ||
| 2544 | + HandleScroll(offset, SCROLL_FROM_UPDATE, NestedState::CHILD_SCROLL); | ||
| 2545 | + } else { | ||
| 2546 | + HandleScrollVelocity(velocity); | ||
| 2547 | + } | ||
| 2548 | + } | ||
| 2549 | + return false; | ||
| 2550 | +} | ||
| 2500 | } // namespace OHOS::Ace::NG | 2551 | } // namespace OHOS::Ace::NG |
| @@ -259,7 +259,7 @@ public: | |||
| 259 | */ | 259 | */ |
| 260 | Axis GetAxis() const override | 260 | Axis GetAxis() const override |
| 261 | { | 261 | { |
| 262 | - return Axis::FREE; | 262 | + return axis_; |
| 263 | } | 263 | } |
| 264 | ScrollResult HandleScroll(float offset, int32_t source, NestedState state) override; | 264 | ScrollResult HandleScroll(float offset, int32_t source, NestedState state) override; |
| 265 | bool HandleScrollVelocity(float velocity) override; | 265 | bool HandleScrollVelocity(float velocity) override; |
| @@ -267,6 +267,7 @@ public: | |||
| 267 | void OnScrollEndRecursive() override; | 267 | void OnScrollEndRecursive() override; |
| 268 | Axis GetParentAxis(); | 268 | Axis GetParentAxis(); |
| 269 | RefPtr<NestableScrollContainer> WebSearchParent(); | 269 | RefPtr<NestableScrollContainer> WebSearchParent(); |
| 270 | + void SetNestedScroll(const NestedScrollOptions& nestedOpt); | ||
| 270 | /** | 271 | /** |
| 271 | * End of NestableScrollContainer implementations | 272 | * End of NestableScrollContainer implementations |
| 272 | */ | 273 | */ |
| @@ -381,6 +382,7 @@ public: | |||
| 381 | { | 382 | { |
| 382 | return rootLayerHeight_; | 383 | return rootLayerHeight_; |
| 383 | } | 384 | } |
| 385 | + bool FilterScrollEvent(const float x, const float y, const float xVelocity, const float yVelocity); | ||
| 384 | 386 | ||
| 385 | private: | 387 | private: |
| 386 | void RegistVirtualKeyBoardListener(); | 388 | void RegistVirtualKeyBoardListener(); |
| @@ -588,6 +590,9 @@ private: | |||
| 588 | bool isMemoryLevelEnable_ = true; | 590 | bool isMemoryLevelEnable_ = true; |
| 589 | bool isFirstFlingScrollVelocity_ = true; | 591 | bool isFirstFlingScrollVelocity_ = true; |
| 590 | bool isWrapContentEnabled_ = false; | 592 | bool isWrapContentEnabled_ = false; |
| 593 | + bool scrollState_ = false; | ||
| 594 | + NestedScrollMode nestedScrollMode_ = NestedScrollMode::SELF_ONLY; | ||
这个为啥不直接用枚举 ![]() ![]()
已修改 ![]() ![]() | |||
| 595 | + Axis axis_ = Axis::FREE; | ||
| 591 | int32_t rootLayerWidth_ = 0; | 596 | int32_t rootLayerWidth_ = 0; |
这个和scrollMode作用看起来是一样的? ![]() ![]() 已修改 ![]() ![]() | |||
| 592 | int32_t rootLayerHeight_ = 0; | 597 | int32_t rootLayerHeight_ = 0; |
| 593 | WeakPtr<NestableScrollContainer> parent_; | 598 | WeakPtr<NestableScrollContainer> parent_; |


改回调是跑在主线程吗,不是的话,可能会有多线程问题