参考文档:https://gitee.com/openharmony/docs/blob/5654c2b940ab3e2f4f0baf435e630c4ef3536428/zh-cn/application-dev/reference/arkui-ts/ts-universal-attributes-component-id.md
通过getInspectorByKey(id: string): string可以获取指定组件信息,那么组件信息中,有一个最有用的信息就是$rect。
$rect
他提供了组件绘制区域的起始点坐标(左上角)结束点坐标(右下角)。
注意:这个坐标是相对于显示屏幕左上角坐标(0,0)的。
如果一个组件绘制在滚动容器内,当容器发生滚动时,这个组件的坐标则会随着滚动而发生变化。
PS:这个设计也很有点难理解,但是也不是不能用。
根据这两个信息,我们可以获取这样的信息:
- 组件的高宽
- 组件相对于屏幕边缘的位置
格式化$rect
$rect返回的是一个字符串
"[起始点x坐标, 起始点y坐标][结束点x坐标, 结束点y坐标]"
我们要使用这两个坐标首先要对这个字符串进行处理
// 记录格式化结果
let rect = null
let rectStr = data['$rect']
//使用正则表达式来处理
rectStr = rectStr.replace(/\s/g, '')
var patt = /\[\d+\.\d+,\d+\.\d+\]+/g;
let arr = rectStr.match(patt)
let startPoint = JSON.parse(arr[0])
let endPoint = JSON.parse(arr[1])
// 结果
rect = {
s: startPoint,
e: endPoint
}
// 打印结果看看
console.log(JSON.stringify(rect))
//[phone][Console DEBUG] 04/25 15:19:55 10596 app Log: {"s":[0,0],"e":[1080,140.96]}
@Entry
@Component
export struct MainPage {
@State index: number = 0
scroller: Scroller = new Scroller()
arrLength = 50
arr = new Array(this.arrLength)
_topBarHeight: number = 0
getRect(id) {
let rect = null
try {
// @ts-ignore
let ins = getInspectorByKey(id)
let data = JSON.parse(ins)
let rectStr = data['$rect']
rectStr = rectStr.replace(/\s/g, '')
var patt = /\[\d+\.\d+,\d+\.\d+\]+/g;
let arr = rectStr.match(patt)
let startPoint = JSON.parse(arr[0])
let endPoint = JSON.parse(arr[1])
rect = {
s: startPoint,
e: endPoint
}
console.log(JSON.stringify(rect))
} catch (e) {
}
return rect
}
build() {
Flex({
direction: FlexDirection.Column
}) {
// 绘制顶部操作栏
Row() {
Counter() {
Text(this.index.toString()).fontSize(20)
}
.width(150)
.onInc(() => {
if (this.index == this.arrLength - 1) return
this.index++
})
.onDec(() => {
if (this.index == 0) return
this.index--
})
Button('jump')
.backgroundColor(Color.White)
.width(100)
.height(40)
.fontColor(Color.Black)
.margin({
left: 10
})
.onClick(() => {
// @ts-ignore
let insObj = this.arr[this.index]
if (!insObj) return
let posY = insObj['s'][1]
this.scroller.scrollTo({
xOffset: 0,
// 滚动位移 = 指定组件位置 - 顶部操作栏高度
yOffset: px2vp(posY) - px2vp(this._topBarHeight)
})
})
}
.padding({
left: 10,
right: 10
})
.backgroundColor(Color.Gray)
.width('100%')
.height(50)
.id('topbar')
.onAppear(() => {
// 记录顶部操作栏高度
let rect = this.getRect('topbar')
if (!rect) return
this._topBarHeight = rect['e'][1] - rect['s'][1]
})
// 绘制滚动列表
Row() {
Scroll(this.scroller) {
Column() {
ForEach(this.arr, (v, i) => {
Flex({
justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center
}) {
Text(i.toString()).fontSize(30)
}
.height(50)
.width('100%')
.id('line' + i)
.backgroundColor(i % 2 == 0? Color.White : '#ddd')
.onAppear(() => {
// 记录所有组件初始绘制信息
let rect = this.getRect('line' + i)
if (!rect) return
this.arr[i] = rect
})
})
}
}
.width('100%')
.height('100%')
}
.width('100%')
.flexGrow(1)
}
}
}