Foreword
this article is based on Api13
in actual development, sliding conflicts are inevitable and are common in the nested use of scrollable container components, such the Scroll component nests the List component, the List component nests the Grid component, and so on. As long as the Scroll container component is nested, the tiresome sliding conflict will come on your face, which is very maddening. How to deal with sliding conflicts has become a required course in development. However, the processing method in Hongmeng seems more intuitive and simple compared with Android. It can be done by using one attribute, that is nestedScroll.
Simple Case
the case is very simple. The outer layer is a Scroll Scroll container, and there is also a List component Scroll component inside. There is a common component on the List.
@Entry
@Component
struct Index {
build() {
Scroll() {
Column() {
Text("我是顶部的组件")
.width("100%")
.height(200)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.fontColor(Color.White)
List() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number) => {
ListItem() {
Text(item.toString())
.width("100%")
.height(80)
.textAlign(TextAlign.Center)
}
})
}
.width("100%")
.height("100%")
.scrollBar(BarState.Off)
.divider({ color: Color.Gray, strokeWidth: 1 })
.edgeEffect(EdgeEffect.None)
}
}.width("100%")
.height("100%")
.scrollBar(BarState.Off)
}
}
The effect is as follows:
the effect we want is to let the top component scroll up first, and then scroll the List component below. We run to see the effect:
obviously, our effect has not been achieved, which is caused by sliding conflicts. In this case, the List component, as a subcomponent, must first hand over the sliding event to the Scroll component, and then hand over the sliding event to itself after the Scroll component rolls to the edge. This process is also correct. How to do it? As mentioned earlier, that is the nestedScroll attribute.
Each scroll container component has a nestedScroll attribute, which mainly solves sliding conflicts in nested scroll mode. We set the List component with the following code:
.nestedScroll({
scrollForward: NestedScrollMode.PARENT_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST
})
after setting up, look at the effect again:
It can be seen that the sliding conflict has been perfectly solved and the desired effect has been achieved.
Understanding nestedScroll
through the case in the foreword, we have basically known the purpose of the nestedScroll property, primarily, it is used to set nested scrolling options and nested scrolling modes in both front and back directions to realize scrolling linkage with the parent component.
Let's focus on the parameter NestedScrollOptions, which has two values, scrollForward and scrollBackward, one for scrolling to the end and the other for scrolling to the beginning.
Both parameters have a common value type the NestedScrollMode has the following values to choose from:
name | description |
---|---|
SELF_ONLY | scrolls only by itself, not with the parent component. |
SELF_FIRST | scrolls itself first, and scrolls itself to the edge before the parent component scrolls. After the parent component scrolls to the edge, if the parent component has an edge effect, the parent component triggers the edge effect, otherwise the child component triggers the edge effect. |
PARENT_FIRST | the parent component scrolls first, and the parent component scrolls to the edge and then scrolls itself. After scrolling to the edge, if there is an edge effect, it will trigger its own edge effect, otherwise it will trigger the edge effect of the parent component. |
PARALLEL | both itself and the parent component scroll at the same time. After both itself and the parent component reach the edge, if it has an edge effect, it triggers the edge effect itself, otherwise the parent component triggers the edge effect. |
Examples of use
in the preface, we simply used the Scroll component to nest the List component as an example. Let's look at a case of the Scroll component nesting the Web component.
import webview from '@ohos.web.webview'
@Entry
@Component
struct Index {
private controller: webview.WebviewController = new webview.WebviewController()
build() {
Scroll() {
Column() {
Text("我是顶部的组件")
.width("100%")
.height(200)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.fontColor(Color.White)
Web({
src: "https://juejin.cn/user/1398234520239095/columns",
controller: this.controller
})
.nestedScroll({
scrollForward: NestedScrollMode.PARENT_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST
})
}
}.width("100%")
.height("100%")
.scrollBar(BarState.Off)
}
}
The above effect is basically the same as that in the foreword, and the effect is no longer pasted. In fact, no matter how many cases are, they are basically the same, except that the values in nestedScroll are different.
Related Summary
in actual development, it is far more complicated than the previous case. For example, the refresh Library I packaged earlier has a refresh head on the scroll component and a load tail on the bottom. There are also more complicated ones, such as list ceiling operation. A nestedScroll attribute is far from enough. It is often combined with sliding monitoring, whether to scroll to the top and tail, etc. to achieve our actual effect.
For example, in the above case, we add a bottom component under the List component, and we run to see the effect:
obviously, the previously configured nestedScroll attribute only satisfies the top component, while the bottom component obviously has sliding conflicts during the sliding process, which does not meet our expectation. In fact, for the bottom, sliding up is to roll itself first and then roll the parent component, while sliding down is to roll the parent component first and then roll its own component.
In view of the above problems, there are actually many ways to deal with them. The simplest one is that the bottom component is under the last component and is treated as part of the List component. Of course, the top component can also do the same, so there is no sliding conflict.
if (index == this.dataArray.length - 1) {
Column() {
Text(item.toString())
.width("100%")
.height(80)
.textAlign(TextAlign.Center)
Text("我是底部的组件")
.width("100%")
.height(200)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
.fontColor(Color.White)
}
}
Let's look at the effect:
There is a problem with adding components to the position of the head and tail data, for example, what if there is no data? The top component and the bottom component cannot be displayed. For example, what if a Grid component or other scroll component is not loaded instead of a List component? Obviously there is a big problem with the handling.
This homework is left to friends. Do you know how to solve it?
This article tags: HarmonyOS/ArkUI/sliding conflict
Top comments (0)