參考文檔: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)
}
}
}