Nested Scrolling with Web Components in HarmonyOS Next
Typical Use Case for Nested Scrolling
Nested scrolling is a common scenario where multiple independent scrollable areas exist on a single page. When a user scrolls through content in one area, it can trigger scrolling in other areas to achieve a seamless up-and-down page scrolling experience.
Key Concepts
-
Nested Scroll Mode: This mode determines how the Web component interacts with its parent scrollable containers. It can be set to different modes such as
SELF_ONLY
,SELF_FIRST
,PARENT_FIRST
, andPARALLEL
. -
NestedScrollOptions: This object contains two properties,
scrollForward
andscrollBackward
, each of which is an enumeration ofNestedScrollMode
.
Example Implementation
The following example demonstrates how to implement nested scrolling with Web components in a HarmonyOS Next application. This example includes buttons to dynamically change the nested scroll mode and displays multiple scrollable areas.
// xxx.ets
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct NestedScroll {
private scrollerForScroll: Scroller = new Scroller();
controller: webview.WebviewController = new webview.WebviewController();
controller2: webview.WebviewController = new webview.WebviewController();
// NestedScrollMode settings
@State NestedScrollMode0: NestedScrollMode = NestedScrollMode.SELF_ONLY;
@State NestedScrollMode1: NestedScrollMode = NestedScrollMode.SELF_FIRST;
@State NestedScrollMode2: NestedScrollMode = NestedScrollMode.PARENT_FIRST;
@State NestedScrollMode3: NestedScrollMode = NestedScrollMode.PARALLEL;
// Current scroll modes
@State NestedScrollModeF: NestedScrollMode = NestedScrollMode.SELF_FIRST;
@State NestedScrollModeB: NestedScrollMode = NestedScrollMode.SELF_FIRST;
// Scroll direction
@State ScrollDirection: ScrollDirection = ScrollDirection.Vertical;
build() {
Flex() {
Scroll(this.scrollerForScroll) {
Column({ space: 5 }) {
Row({}) {
Text('Scroll Mode Before').fontSize(5)
Button('SELF_ONLY').onClick((event: ClickEvent) => {
this.NestedScrollModeF = this.NestedScrollMode0;
}).fontSize(5)
Button('SELF_FIRST').onClick((event: ClickEvent) => {
this.NestedScrollModeF = this.NestedScrollMode1;
}).fontSize(5)
Button('PARENT_FIRST').onClick((event: ClickEvent) => {
this.NestedScrollModeF = this.NestedScrollMode2;
}).fontSize(5)
Button('PARALLEL').onClick((event: ClickEvent) => {
this.NestedScrollModeF = this.NestedScrollMode3;
}).fontSize(5)
}
Row({}) {
Text('Scroll Mode After').fontSize(5)
Button('SELF_ONLY').onClick((event: ClickEvent) => {
this.NestedScrollModeB = this.NestedScrollMode0;
}).fontSize(5)
Button('SELF_FIRST').onClick((event: ClickEvent) => {
this.NestedScrollModeB = this.NestedScrollMode1;
}).fontSize(5)
Button('PARENT_FIRST').onClick((event: ClickEvent) => {
this.NestedScrollModeB = this.NestedScrollMode2;
}).fontSize(5)
Button('PARALLEL').onClick((event: ClickEvent) => {
this.NestedScrollModeB = this.NestedScrollMode3;
}).fontSize(5)
}
Text('Current Scroll Mode Before ---' + `${this.NestedScrollModeF}`).fontSize(10)
Text('Current Scroll Mode After ---' + `${this.NestedScrollModeB}`).fontSize(10)
Text("Scroll Area")
.width("100%")
.height("10%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
Text("Scroll Area")
.width("100%")
.height("10%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
Text("Scroll Area")
.width("100%")
.height("10%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
Web({ src: "https://www.example.com", controller: this.controller })
.nestedScroll({
scrollForward: this.NestedScrollModeF,
scrollBackward: this.NestedScrollModeB,
})
.height("40%")
.width("100%")
Text("Scroll Area")
.width("100%")
.height("20%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
Text("Scroll Area")
.width("100%")
.height("20%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
Web({ src: "https://www.example.com", controller: this.controller2 })
.nestedScroll({
scrollForward: this.NestedScrollModeF,
scrollBackward: this.NestedScrollModeB,
})
.height("40%")
.width("90%")
Text("Scroll Area")
.width("100%")
.height("20%")
.backgroundColor(0X330000FF)
.fontSize(16)
.textAlign(TextAlign.Center)
}.width("95%").border({ width: 5 })
}
.width("100%").height("120%").border({ width: 5 }).scrollable(this.ScrollDirection)
}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
}
}
Explanation
-
NestedScrollMode: This enumeration defines how the Web component should handle nested scrolling. Options include:
-
SELF_ONLY
: The Web component scrolls independently without interacting with the parent. -
SELF_FIRST
: The Web component scrolls first, and if it reaches the edge, the parent container continues scrolling. -
PARENT_FIRST
: The parent container scrolls first, and if it reaches the edge, the Web component continues scrolling. -
PARALLEL
: Both the Web component and the parent container scroll simultaneously.
-
-
nestedScroll: This property is used to set the nested scroll behavior for the Web component. It takes a
NestedScrollOptions
object withscrollForward
andscrollBackward
properties. - Buttons: These allow the user to dynamically change the nested scroll mode during runtime.
Supported Containers and Input Events
- Supported Containers: Grid, List, Scroll, Swiper, Tabs, WaterFlow.
- Supported Input Events: Gestures, mouse, touchpad.
Top comments (0)