天天看點

【OpenHarmony應用開發】eTS通用屬性 - 元件辨別(三)$rect格式化$rect

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

           

繼續閱讀