OpenHarmony应用开发-容器组件Scroll/Scroller/SideBarContainer
版本:v3.2 Release
Scroll
可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
说明:
- 该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
- 该组件嵌套List子组件滚动时,若List不设置宽高,则默认全部加载,在对性能有要求的场景下建议指定List的宽高。
- 该组件滚动的前提是主轴方向大小小于内容大小。
- 该组件回弹的前提是要有滚动。内容小于一屏时,没有回弹效果。
子组件
支持单个子组件。
接口
Scroll(scroller?: Scroller)
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
scroller | 否 | 可滚动组件的控制器。用于与可滚动组件进行绑定。 |
属性
除支持通用属性外,还支持以下属性:
名称 | 参数类型 | 描述 |
scrollable | 设置滚动方向。 默认值:ScrollDirection.Vertical | |
scrollBar | 设置滚动条状态。 默认值:BarState.Auto 说明: 如果容器组件无法滚动,则滚动条不显示。 | |
scrollBarColor | string | number | Color | 设置滚动条的颜色。 |
scrollBarWidth | string | number | 设置滚动条的宽度。 默认值:4 单位:vp |
edgeEffect | 设置滑动效果,目前支持的滑动效果参见EdgeEffect的枚举说明。 默认值:EdgeEffect.None |
ScrollDirection枚举说明
名称 | 描述 |
Horizontal | 仅支持水平方向滚动。 |
Vertical | 仅支持竖直方向滚动。 |
None | 不可滚动。 |
Free(deprecated) | 支持竖直或水平方向滚动 从API version 9开始废弃 |
事件
名称 | 功能描述 |
onScrollFrameBegin9+(event: (offset: number, state: ScrollState) => { offsetRemain }) | 每帧开始滚动时触发,事件参数传入即将发生的滚动量,事件处理函数中可根据应用场景计算实际需要的滚动量并作为事件处理函数的返回值返回,Scroll将按照返回值的实际滚动量进行滚动。 - offset:即将发生的滚动量。 - state:当前滚动状态。 - offsetRemain:实际滚动量。 触发该事件的条件 : 1、滚动组件触发滚动时触发,包括键鼠操作等其他触发滚动的输入设置。 2、调用控制器接口时不触发。 3、越界回弹不触发。 说明: 支持offsetRemain为负值。 若通过onScrollFrameBegine事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None。 |
onScroll(event: (xOffset: number, yOffset: number) => void) | 滚动事件回调, 返回滚动时水平、竖直方向偏移量。 触发该事件的条件 : 1、滚动组件触发滚动时触发,支持键鼠操作等其他触发滚动的输入设置。 2、通过滚动控制器API接口调用。 3、越界回弹。 |
onScrollEdge(event: (side: Edge) => void) | 滚动到边缘事件回调。 触发该事件的条件 : 1、滚动组件触发滚动时触发,支持键鼠操作等其他触发滚动的输入设置。 2、通过滚动控制器API接口调用。 3、越界回弹。 |
onScrollEnd(deprecated) (event: () => void) | 滚动停止事件回调。 该事件从API version 9开始废弃,使用onScrollStop事件替代。 触发该事件的条件 : 1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。 2、通过滚动控制器API接口调用后停止,带过渡动效。 |
onScrollStart9+(event: () => void) | 滚动开始时触发。手指拖动Scroll或拖动Scroll的滚动条触发的滚动开始时,会触发该事件。使用Scroller滚动控制器触发的带动画的滚动,动画开始时会触发该事件。 触发该事件的条件 : 1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。 2、通过滚动控制器API接口调用后开始,带过渡动效。 |
onScrollStop9+(event: () => void) | 滚动停止时触发。手拖动Scroll或拖动Scroll的滚动条触发的滚动,手离开屏幕并且滚动停止时会触发该事件。使用Scroller滚动控制器触发的带动画的滚动,动画停止时会触发该事件。 触发该事件的条件 : 1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。 2、通过滚动控制器API接口调用后开始,带过渡动效,。 |
说明:
若通过onScrollFrameBegin事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None。
Scroller
可滚动容器组件的控制器,可以将此组件绑定至容器组件,然后通过它控制容器组件的滚动,同一个控制器不可以控制多个容器组件,目前支持绑定到List、Scroll、ScrollBar、Grid上。
导入对象
scroller: Scroller = new Scroller()
scrollTo
scrollTo(value: { xOffset: number | string, yOffset: number | string, animation?: { duration: number, curve: Curve } }): void
滑动到指定位置。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
xOffset | number | string | 是 | 水平滑动偏移。 说明: 该参数值不支持设置百分比。 仅滚动轴为x轴时生效。 |
yOffset | number | string | 是 | 垂直滑动偏移。 说明: 该参数值不支持设置百分比。 仅滚动轴为y轴时生效。 |
animation | { duration: number, curve: Curve} | 否 | 动画配置: - duration: 滚动时长设置。 - curve: 滚动曲线设置。 默认值: { duration: 0, curve: Curve.Ease } 说明: 设置为小于0的值时,按默认值显示。 |
scrollEdge
scrollEdge(value: Edge): void
滚动到容器边缘,不区分滚动轴方向,Edge.Top和Edge.Start表现相同,Edge.Bottom和Edge.End表现相同。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
value | Edge | 是 | 滚动到的边缘位置。 |
scrollPage
scrollPage(value: { next: boolean, direction?: Axis }): void
滚动到下一页或者上一页。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
next | boolean | 是 | 是否向下翻页。true表示向下翻页,false表示向上翻页。 |
direction(deprecated) | Axis | 否 | 设置滚动方向为水平或竖直方向。 从API version 9开始废弃 |
currentOffset
currentOffset(): { xOffset: number, yOffset: number }
返回当前的滚动偏移量。
返回值
类型 | 描述 |
{ xOffset: number, yOffset: number } | xOffset: 水平滑动偏移; yOffset: 竖直滑动偏移。 说明: 返回值单位为vp。 |
scrollToIndex
scrollToIndex(value: number): void
滑动到指定Index。
说明:
仅支持Grid、List组件。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
value | number | 是 | 要滑动到的列表项在列表中的索引值。 |
scrollBy9+
scrollBy(dx: Length, dy: Length): void
滑动指定距离。
说明:
仅支持Scroll、ScrollBar、Grid、List组件。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
dx | Length | 是 | 水平方向滚动距离,不支持百分比形式。 |
dy | Length | 是 | 竖直方向滚动距离,不支持百分比形式。 |
示例
示例1
// xxx.ets
@Entry
@Component
struct ScrollExample {
scroller: Scroller = new Scroller()
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
build() {
Stack({ alignContent: Alignment.TopStart }) {
Scroll(this.scroller) {
Column() {
ForEach(this.arr, (item) => {
Text(item.toString())
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
}, item => item)
}.width('100%')
}
.scrollable(ScrollDirection.Vertical) // 滚动方向纵向
.scrollBar(BarState.On) // 滚动条常驻显示
.scrollBarColor(Color.Gray) // 滚动条颜色
.scrollBarWidth(10) // 滚动条宽度
.edgeEffect(EdgeEffect.None)
.onScroll((xOffset: number, yOffset: number) => {
console.info(xOffset + ' ' + yOffset)
})
.onScrollEdge((side: Edge) => {
console.info('To the edge')
})
.onScrollEnd(() => {
console.info('Scroll Stop')
})
Button('scroll 150')
.height('5%')
.onClick(() => { // 点击后下滑指定距离150.0vp
this.scroller.scrollBy(0,150)
})
.margin({ top: 10, left: 20 })
Button('scroll 100')
.height('5%')
.onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离
this.scroller.scrollTo({ xOffset: 0, yOffset: this.scroller.currentOffset().yOffset + 100 })
})
.margin({ top: 60, left: 20 })
Button('back top')
.height('5%')
.onClick(() => { // 点击后回到顶部
this.scroller.scrollEdge(Edge.Top)
})
.margin({ top: 110, left: 20 })
Button('next page')
.height('5%')
.onClick(() => { // 点击后滑到下一页
this.scroller.scrollPage({ next: true })
})
.margin({ top: 170, left: 20 })
}.width('100%').height('100%').backgroundColor(0xDCDCDC)
}
}
示例2
@Entry
@Component
struct NestedScroll {
@State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。
private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
private scrollerForScroll: Scroller = new Scroller()
private scrollerForList: Scroller = new Scroller()
build() {
Flex() {
Scroll(this.scrollerForScroll) {
Column() {
Text("Scroll Area")
.width("100%").height("40%").backgroundColor(0X330000FF)
.fontSize(16).textAlign(TextAlign.Center)
.onClick(() => {
this.scrollerForList.scrollToIndex(5)
})
List({ space: 20, scroller: this.scrollerForList }) {
ForEach(this.arr, (item) => {
ListItem() {
Text("ListItem" + item)
.width("100%").height("100%").borderRadius(15)
.fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
}.width("100%").height(100)
}, item => item)
}
.width("100%")
.height("50%")
.edgeEffect(EdgeEffect.None)
.onReachStart(() => {
this.listPosition = 0
})
.onReachEnd(() => {
this.listPosition = 2
})
.onScrollFrameBegin((offset: number) => {
if ((this.listPosition == 0 && offset <= 0) || (this.listPosition == 2 && offset >= 0)) {
this.scrollerForScroll.scrollBy(0, offset)
return { offsetRemain: 0 }
}
this.listPosition = 1
return { offsetRemain: offset };
})
Text("Scroll Area")
.width("100%").height("40%").backgroundColor(0X330000FF)
.fontSize(16).textAlign(TextAlign.Center)
}
}
.width("100%").height("100%")
}.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
}
}
SideBarContainer
提供侧边栏可以显示和隐藏的侧边栏容器,通过子组件定义侧边栏和内容区,第一个子组件表示侧边栏,第二个子组件表示内容区。
说明:
该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
子组件
可以包含子组件。
说明:
- 子组件类型:系统组件和自定义组件,不支持渲染控制类型(if/else、ForEach和LazyForEach)。
- 子组件个数:必须且仅包含2个子组件。
- 子组件个数异常时:3个或以上子组件,显示第一个和第二个。1个子组件,显示侧边栏,内容区为空白。
接口
SideBarContainer( type?: SideBarContainerType )
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
type | SideBarContainerType | 否 | 设置侧边栏的显示类型。 默认值:SideBarContainerType.Embed |
SideBarContainerType枚举说明
名称 | 描述 |
Embed | 侧边栏嵌入到组件内,和内容区并列显示。 |
Overlay | 侧边栏浮在内容区上面。 |
属性
除支持通用属性外,还支持以下属性:
名称 | 参数类型 | 描述 |
showSideBar | boolean | 设置是否显示侧边栏。 默认值:true |
controlButton | 设置侧边栏控制按钮的属性。 | |
showControlButton | boolean | 设置是否显示控制按钮。 默认值:true |
sideBarWidth | number | Length9+ | 设置侧边栏的宽度。 默认值:200 单位:vp 说明: 设置为小于0的值时按默认值显示。 受最小宽度和最大宽度限制,不在限制区域内取最近的点。 sideBarWidth优先于侧边栏子组件width,sideBarWidth未设置时默认值优先级低于侧边栏子组件width。 |
minSideBarWidth | number | Length9+ | 设置侧边栏最小宽度。 默认值:200,单位vp 说明: 设置为小于0的值时按默认值显示。 值不能超过侧边栏容器本身宽度,超过使用侧边栏容器本身宽度。 minSideBarWidth优先于侧边栏子组件minWidth,minSideBarWidth未设置时默认值优先级低于侧边栏子组件minWidth。 |
maxSideBarWidth | number | Length9+ | 设置侧边栏最大宽度。 默认值:280,单位vp 说明: 设置为小于0的值时按默认值显示。 值不能超过侧边栏容器本身宽度,超过使用侧边栏容器本身宽度。 maxSideBarWidth优先于侧边栏子组件maxWidth,maxSideBarWidth未设置时默认值优先级低于侧边栏子组件maxWidth。 |
autoHide9+ | boolean | 设置当侧边栏拖拽到小于最小宽度后,是否自动隐藏。 默认值:true 说明: 受minSideBarWidth属性方法影响,minSideBarWidth属性方法未设置值使用默认值。 拖拽过程中判断是否要自动隐藏。小于最小宽度时需要阻尼效果触发隐藏(越界一段距离) |
sideBarPosition9+ | SideBarPosition | 设置侧边栏显示位置。 默认值:SideBarPosition.Start |
ButtonStyle对象说明
名称 | 参数类型 | 必填 | 描述 |
left | number | 否 | 设置侧边栏控制按钮距离容器左界限的间距。 默认值:16 单位:vp |
top | number | 否 | 设置侧边栏控制按钮距离容器上界限的间距。 默认值:48 单位:vp |
width | number | 否 | 设置侧边栏控制按钮的宽度。 默认值:32 单位:vp |
height | number | 否 | 设置侧边栏控制按钮的高度。 默认值:32 单位:vp |
icons | { shown: string | PixelMap | Resource , hidden: string | PixelMap | Resource , switching?: string | PixelMap | Resource} | 否 | 设置侧边栏控制按钮的图标: - shown: 设置侧边栏显示时控制按钮的图标。 说明: 资源获取错误时,使用默认图标。 - hidden: 设置侧边栏隐藏时控制按钮的图标。 - switching:设置侧边栏显示和隐藏状态切换时控制按钮的图标。 |
SideBarPosition9+枚举说明
名称 | 描述 |
Start | 侧边栏位于容器左侧。 |
End | 侧边栏位于容器右侧。 |
事件
除支持通用事件外,还支持以下事件:
名称 | 功能描述 |
onChange(callback: (value: boolean) => void) | 当侧边栏的状态在显示和隐藏之间切换时触发回调。true表示显示,false表示隐藏。 触发该事件的条件: 1、showSideBar属性值变换时; 2、showSideBar属性自适应行为变化时; 3、分割线拖拽触发autoHide时。 |
示例
// xxx.ets
@Entry
@Component
struct SideBarContainerExample {
normalIcon : Resource = $r("app.media.icon")
selectedIcon: Resource = $r("app.media.icon")
@State arr: number[] = [1, 2, 3]
@State current: number = 1
build() {
SideBarContainer(SideBarContainerType.Embed)
{
Column() {
ForEach(this.arr, (item, index) => {
Column({ space: 5 }) {
Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64)
Text("Index0" + item)
.fontSize(25)
.fontColor(this.current === item ? '#0A59F7' : '#999')
.fontFamily('source-sans-pro,cursive,sans-serif')
}
.onClick(() => {
this.current = item
})
}, item => item)
}.width('100%')
.justifyContent(FlexAlign.SpaceEvenly)
.backgroundColor('#19000000')
Column() {
Text('SideBarContainer content text1').fontSize(25)
Text('SideBarContainer content text2').fontSize(25)
}
.margin({ top: 50, left: 20, right: 30 })
}
.sideBarWidth(150)
.minSideBarWidth(50)
.maxSideBarWidth(300)
.onChange((value: boolean) => {
console.info('status:' + value)
})
}
}
Stack
堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
说明:
该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
子组件
可以包含子组件。
接口
Stack(value?: { alignContent?: Alignment })
从API version 9开始,该接口支持在ArkTS卡片中使用。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
alignContent | 否 | 设置子组件在容器内的对齐方式。 默认值:Alignment.Center |
属性
除支持通用属性外,还支持以下属性:
名称 | 参数类型 | 描述 |
alignContent | 设置子组件在容器内的对齐方式。 默认值:Alignment.Center 从API version 9开始,该接口支持在ArkTS卡片中使用。 |
示例
// xxx.ets
@Entry
@Component
struct StackExample {
build() {
Stack({ alignContent: Alignment.Bottom }) {
Text('First child, show in bottom').width('90%').height('100%').backgroundColor(0xd2cab3).align(Alignment.Top)
Text('Second child, show in top').width('70%').height('60%').backgroundColor(0xc1cbac).align(Alignment.Top)
}.width('100%').height(150).margin({ top: 5 })
}
}
Swiper
滑块视图容器,提供子组件滑动轮播显示的能力。
说明:
该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
子组件
可以包含子组件。
说明:
子组件类型:系统组件和自定义组件,支持渲染控制类型(if/else、ForEach和LazyForEach)。
接口
Swiper(controller?: SwiperController)
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
controller | 否 | 给组件绑定一个控制器,用来控制组件翻页。 |
属性
除支持通用属性外,还支持以下属性,不支持Menu控制。
名称 | 参数类型 | 描述 |
index | number | 设置当前在容器中显示的子组件的索引值。 默认值:0 说明: 设置小于0或大于等于子组件数量时,按照默认值0处理。 |
autoPlay | boolean | 子组件是否自动播放。 默认值:false 说明: loop为false时,自动轮播到最后一页时停止轮播。手势切换后不是最后一页时继续播放。 |
interval | number | 使用自动播放时播放的时间间隔,单位为毫秒。 默认值:3000 |
indicator | boolean | 是否启用导航点指示器。 默认值:true |
loop | boolean | 是否开启循环。 设置为true时表示开启循环,在LazyForEach懒循环加载模式下,加载的组件数量建议大于5个。 默认值:true |
duration | number | 子组件切换的动画时长,单位为毫秒。 默认值:400 |
vertical | boolean | 是否为纵向滑动。 默认值:false |
itemSpace | number | string | 设置子组件与子组件之间间隙。 默认值:0 说明: 不支持设置百分比。 |
displayMode | SwiperDisplayMode | 主轴方向上元素排列的模式,优先以displayCount设置的个数显示,displayCount未设置时本属性生效。 默认值:SwiperDisplayMode.Stretch |
cachedCount8+ | number | 设置预加载子组件个数。 默认值:1 |
disableSwipe8+ | boolean | 禁用组件滑动切换功能。 默认值:false |
curve8+ | Curve | string | 设置Swiper的动画曲线,默认为淡入淡出曲线,常用曲线参考Curve枚举说明,也可以通过插值计算模块提供的接口创建自定义的插值曲线对象。 默认值:Curve.Ease |
indicatorStyle8+ | { left?: Length, top?: Length, right?: Length, bottom?: Length, size?: Length, mask?: boolean, color?: ResourceColor, selectedColor?: ResourceColor} | 设置导航点样式: - left: 设置导航点距离Swiper组件左边的距离。 - top: 设置导航点距离Swiper组件顶部的距离。 - right: 设置导航点距离Swiper组件右边的距离。 - bottom: 设置导航点距离Swiper组件底部的距离。 - size: 设置导航点的直径。 - mask: 设置是否显示导航点蒙层样式。 - color: 设置导航点的颜色。 - selectedColor: 设置选中的导航点的颜色。 |
displayCount8+ | number|string | 设置一页内元素显示个数。 默认值:1 说明: 字符串类型仅支持设置为’auto’,显示效果同SwiperDisplayMode.AutoLinear。 使用number类型时,子组件按照主轴均分Swiper宽度(减去displayCount-1的itemSpace)的方式进行主轴拉伸(收缩)布局。 |
effectMode8+ | 滑动效果,目前支持的滑动效果参见EdgeEffect的枚举说明。 默认值:EdgeEffect.Spring 说明: 控制器接口调用时不生效回弹。 |
SwiperDisplayMode枚举说明
名称 | 描述 |
Stretch | Swiper滑动一页的宽度为Swiper组件自身的宽度。 |
AutoLinear | Swiper滑动一页的宽度为子组件宽度中的最大值。 |
SwiperController
Swiper容器组件的控制器,可以将此对象绑定至Swiper组件,然后通过它控制翻页。
showNext
showNext(): void
翻至下一页。翻页带动效切换过程,时长通过duration指定。
showPrevious
showPrevious(): void
翻至上一页。翻页带动效切换过程,时长通过duration指定。
finishAnimation
finishAnimation(callback?: () => void): void
停止播放动画。
参数:
参数名 | 参数类型 | 必填项 | 参数描述 |
callback | () => void | 否 | 动画结束的回调。 |
事件
除支持通用事件外,还支持以下事件:
名称 | 功能描述 |
onChange(event: (index: number) => void) | 当前显示的子组件索引变化时触发该事件,返回值为当前显示的子组件的索引值。 - index:当前显示元素的索引。 说明: Swiper组件结合LazyForEach使用时,不能在onChange事件里触发子页面UI的刷新。 |
onAnimationStart9+(event: (index: number) => void) | 切换动画开始时触发该回调。 - index:当前显示元素的索引。 说明: 参数为动画开始前的index值(不是最终结束动画的index值),多列Swiper时,index为最左侧组件的索引。 |
onAnimationEnd9+(event: (index: number) => void) | 切换动画结束时触发该回调。 - index:当前显示元素的索引。 说明: 当Swiper切换动效结束时触发,包括动画过程中手势中断,通过SwiperController调用finishAnimatio。参数为动画结束后的index值,多列Swiper时,index为最左侧组件的索引。 |
示例
// xxx.ets
class MyDataSource implements IDataSource {
private list: number[] = []
private listener: DataChangeListener
constructor(list: number[]) {
this.list = list
}
totalCount(): number {
return this.list.length
}
getData(index: number): any {
return this.list[index]
}
registerDataChangeListener(listener: DataChangeListener): void {
this.listener = listener
}
unregisterDataChangeListener() {
}
}
@Entry
@Component
struct SwiperExample {
private swiperController: SwiperController = new SwiperController()
private data: MyDataSource = new MyDataSource([])
aboutToAppear(): void {
let list = []
for (var i = 1; i <= 10; i++) {
list.push(i.toString());
}
this.data = new MyDataSource(list)
}
build() {
Column({ space: 5 }) {
Swiper(this.swiperController) {
LazyForEach(this.data, (item: string) => {
Text(item).width('90%').height(160).backgroundColor(0xAFEEEE).textAlign(TextAlign.Center).fontSize(30)
}, item => item)
}
.cachedCount(2)
.index(1)
.autoPlay(true)
.interval(4000)
.indicator(true)
.loop(true)
.duration(1000)
.itemSpace(0)
.curve(Curve.Linear)
.onChange((index: number) => {
console.info(index.toString())
})
Row({ space: 12 }) {
Button('showNext')
.onClick(() => {
this.swiperController.showNext()
})
Button('showPrevious')
.onClick(() => {
this.swiperController.showPrevious()
})
}.margin(5)
}.width('100%')
.margin({ top: 5 })
}
}