可滚动的容器组件,当子组件的布局尺寸超过Scroll的尺寸时,内容可以滚动。当页面内容由多个区域组成,并且可以滚动时,推荐使用 Scroll。
1.核心用法
- Scroll 设置尺寸
- 设置 子组件(只支持一个子组件)
- 设置滚动:
- 竖向滚动:子组件的高度超出 Scroll
- 横向滚动:子组件的宽度超出 Scroll,scrollable改为横向滚动
- 根据需求调整属性
Scroll(){
// 只支持一个子组件
Column(){
// 内容放在内部
// 尺寸超过 200 即可滚动
}
}
.width('100%')
.height(200)
注意:column里面只能有一个子组件,可以在最外层包裹一个column或者row等等,然后在里面在进行写其他组件
举例:
.scrollBarColor(Color.Pink)//滚动条颜色
.scrollBarWidth(50)//滚动条宽度
.scrollBar(BarState.Off)//关闭滚动条
.edgeEffect(EdgeEffect.Spring)//弹簧效果
.scrollable(ScrollDirection.Horizontal)//设置滚动条的方向
2.Scroll的控制器
有两个方法:
- scrollEdge:滚动到边缘
- currentOffset: 获取当前的偏移量
举例:
- 页面滚动超过一定距离,显示返回顶部(火箭),反之隐藏
- 点击返回顶部(火箭),返回顶部
核心步骤:
- 实例化 Scroller的 控制器
- 绑定给 Scroll
- 调用 控制器的方法控制滚动,通过控制器的属性获取滚动距离
先实现点击火箭马上返回到顶部
@Entry
@Component
struct ScrollDemo {
//1.实例化Scroller的 控制器
scroller: Scroller = new Scroller()
build() {
Column() {
//2绑定给Scroll
Scroll(this.scroller) {
// 内容略
}
Row() {
Button('返回顶部')
.onClick(() => {
// 滚到顶部,利用scroller上的scrollEdge方法
this.scroller.scrollEdge(Edge.Top)
})
scrollEdge方法参数
this.scroller.scrollEdge(Edge.Top)
this.scroller.scrollEdge(Edge.Start)
this.scroller.scrollEdge(Edge.Bottom)
this.scroller.scrollEdge(Edge.End)
其中的Edge.Top和Edge.Start表现相同,Edge.Bottom和Edge.End表现相同。
currentOffset 方法返回值
this.scroller.currentOffset().xOffset // x 轴滚动距离
this.scroller.currentOffset().yOffset // y 轴滚动距离
onWillScroll事件
Scroll(){
// 内容略
}
.onScroll((x,y)=>{
// 滚动时 一直触发
// 可以结合 scroller的currentOffset方法 获取滚动距离
})
说明:onScroll在进行滑动的时候可以一直获取滑动的x,y距离,并且能返回一个值
上面的京东案例(部分代码)
1.先实例化Scroller
sc: Scroller = new Scroller()
@State showRocket: boolean = false
...
//在Scroll组件上.出这个属性然后进行随时获取x和y的滑动距离
.onScroll((x, y) => {
if( this.sc.currentOffset().yOffset>400){
this.showRocket=true
}else{
this.showRocket = false
}
})
//这里在进行条件渲染,当y的距离超过400时就显示火箭图标
if (this.showRocket) {
Image($r('app.media.ic_jd_rocket'))
.width(40)
.backgroundColor(Color.White)
.borderRadius(20)
.padding(5)
.offset({ x: -20, y: -20 })
.onClick(() => {
this.sc.scrollEdge(Edge.Top)
})
}
3. 容器组件Tabs
当页面内容较多时,可以通过Tabs组件进行分类展示,以下这些效果都可以通过Tabs组件来实现
3.1基本用法
@Entry
@Component
struct TabbarDemo {
build() {
Tabs() { // 顶级容器
TabContent() {
// 内容区域:只能有一个子组件
}
.tabBar('首页') // 导航栏
}
}
}
注意:TabContent里面只能有一个子组件,可以使用column和row等组件进行包裹
3.2常用属性
Tabs默认可以实现切换,可以设置如下图导航位置
相关属性:
// BarPosition.Start 起始
// BarPosition.End 结尾
Tabs({ barPosition: BarPosition.End }) {
// 内容略
}
.vertical(true)// 垂直导航 true / 水平false
.scrollable(true) // 允许滑动 true / 不允许 false
.animationDuration(0) // 切换动画的时间,毫秒
注意:BarPosition可以设置在Tabs括号里面,也可以设置在右括号的外面。
3.3滚动的导航栏
也可以设置导航栏的滚动,也可以进行固定,但是如果导航的数量太多了就会显示不全: 如:
使用可以通过设置
.barMode(BarMode.Scrollable)// 滚动
3.4自定义tabBar
在开发中,可能会遇到如下外观的导航栏
那么这个时候就需要进行自定义样式了
基本语法如下:
Tabs() {
TabContent() {
// 内容略
}
//在这里进行引用
.tabBar(this.tabBarBuilder())
}
@Builder
tabBarBuilder() {
// 这里进行自定义的Tabbar结构
Column() {
Image(img)
.width(30)
Text(text)
}
}
3.5 Tabs组件的事件
自定义的导航栏在滑动时不会被点亮,那么就需要引入事件了
//onChange在切换时会有延时效果,一般需要与.animationDuration(0)进行结合使用,而且不管时滑动和点击是都能触发相应的效果
.onChange((index) => {
console.log('onChange-index:', index)
})
//onTabBarClick没有延时效果,但是它只能在点击时能触发相应的效果
.onTabBarClick((index) => {
console.log('tabBarClick-index:', index)
})
注意:这两个的特点是都可以获取导航栏的索引值,而且都是从0开始的。
3.5.1 自定义 tabBar-高亮切换
思路:
- 用状态变量保存,onChange,ontabBarClick中获取到的索引值
- 给每个 tabBar起个标记,0,1,2.。。
- 在tabBar内部比较 标记==this.index?高亮:不高亮
关键代码:
// 1. ✨✨✨定义一个状态变量,用来存储当前用户选中的tabbar索引
@State currentIndex: number = 0
// 2. 定义构建函数
@Builder
tabbarBuilder(title: string, icon: string, selectedIcon: string, index: number) {
Column({ space: 5 }) {
// 3. ✨✨✨在自定义构建函数中使用三元表达式来进行高亮功能的处理
Image(this.currentIndex == index ? $r(selectedIcon) : $r(icon))
.width(35)
Text(title)
// 4. ✨✨✨在自定义构建函数中使用三元表达式来进行高亮功能的处理
.fontColor(this.currentIndex == index ? Color.Red : Color.Black)
}
}
Tabs() {
TabContent() {
Text('首页')
.fontSize(50)
}
// 5. ✨✨✨在调用自定义构建函数的时候,需要传入当前tabbar的索引(固定值),同时要传入点亮的图片路径和正常的图片路径
.tabBar(this.tabbarBuilder('首页', 'app.media.ic_tabbar_icon_0', 'app.media.ic_tabbar_icon_0_selected', 0))
//6.将索引值index赋给状态变量
//这里使用animationDuration配合使用消除延时
.animationDuration(0)
.onChange((index) => {
this.currentIndex = index
})
3.6 Badge角标组件
Badge({
//这里count为number类型,也可以换成value,他是一个字符串类型
count: 8,
style: {},
position: { x: 25, y: -5 }
}) {
//这里表示这个角标放在Text的身上
Text(title)
.fontWeight(this.a == index ? 800 : 400)
.fontColor(Color.Gray)
}