純血鴻蒙APP實戰開發——左右拖動切換圖片效果案例

介紹

本示例使用滑動手勢監聽,實時調整左右兩側內容顯示區域大小和效果。通過綁定gesture事件中的PanGesture平移手勢,實時獲取拖動距離。當拖動時,實時地調節左右兩個Image組件的寬度,從而成功實現左右拖動切換圖片效果的功能。

效果圖預覽

使用說明

  1. 點擊中間按鈕進行左右拖動切換圖片。

實現思路

本例涉及的關鍵特性和實現方案如下:

  1. 創建兩個Stack組件,用來展示裝修前后對比圖,左右兩個Stack分別存放裝修前的圖片和裝修后的圖片,zIndex設置為1。中間Column組件存放按鈕的圖片,zIndex設置為2,這樣按鈕的圖片就會覆蓋在兩張裝修圖片之上。
Row() {
  Stack() {...}
  .zIndex(CONFIGURATION.ZINDEX1)
  .width(this.leftImageWidth) // z序設為1,為了使按鈕圖片浮在裝修圖片上。
  .clip(true)
  .alignContent(Alignment.TopStart)

  Column() {...}
  .width($r('app.integer.dragtoswitchpictures_drag_button_stack_width'))
  .zIndex(CONFIGURATION.ZINDEX2) // z序設為2,為了使按鈕圖片浮在裝修圖片上。

  Stack() {...}
  .zIndex(CONFIGURATION.ZINDEX1) // z序設為1,為了使按鈕圖片浮在裝修圖片上。
  .clip(true)
  .width(this.rightImageWidth)
  .alignContent(Alignment.TopEnd)
}
.justifyContent(FlexAlign.Center)
.width($r('app.string.dragtoswitchpictures_full_size'))
  1. 將Image組件放在Row容器里,將Row容器的寬度設置為狀態變量,再利用clip屬性對于Row容器進行裁剪。
Row() {
  Image($r('app.media.dragtoswitchpictures_before_decoration'))
    .width($r('app.integer.dragtoswitchpictures_decoration_width'))// Image的width固定,Row的寬度變化,通過裁剪實現布局效果。
    .height($r('app.integer.dragtoswitchpictures_decoration_height'))
    .draggable(false) // 設置Image不能拖動,不然長按Image會被拖動。
  }
  .width(this.leftImageWidth) // 將左側Row的width設置為leftImageWidth,這樣左側Row的width隨leftImageWidth的變化而變化。
  .clip(true) // clip屬性設置為true,裁剪超出Row寬度的圖片。
  .zIndex(CONFIGURATION.ZINDEX1) // z序設為1,為了使水印浮在裝修圖片上。
  .borderRadius({
    topLeft: $r('app.integer.dragtoswitchpictures_borderradius'),
    bottomLeft: $r('app.integer.dragtoswitchpictures_borderradius')
  }) // 將Row的左上角和左下角弧度設為10實現效果。
  1. 右邊的Image組件與左邊同樣的操作,但是新增了一個direction屬性,使元素從右至左進行布局,為的是讓Row從左側開始裁剪。
Row() {
 Image($r('app.media.dragtoswitchpictures_after_decoration'))
   .width($r('app.integer.dragtoswitchpictures_decoration_width'))
   .height($r('app.integer.dragtoswitchpictures_decoration_height'))
   .draggable(false)
}
.width(this.rightImageWidth)
.clip(true)
.zIndex(CONFIGURATION.ZINDEX1) // z序設為1,為了使水印浮在裝修圖片上。
// TODO: 知識點:左邊Row使用clip時從右邊開始裁剪,加了Direction.Rtl后,元素從右到左布局,右邊Row使用clip時從左邊開始裁剪,這是實現滑動改變視圖內容大小的關鍵。
.direction(Direction.Rtl)
.borderRadius({
 topRight: $r('app.integer.dragtoswitchpictures_borderradius'),
 bottomRight: $r('app.integer.dragtoswitchpictures_borderradius')
}) // 將Row的右上角和右下角弧度設為10實現效果。
  1. 中間的Image組件通過手勢事件中的滑動手勢對Image組件滑動進行監聽,對左右Image組件的寬度進行計算從而重新布局渲染。
Image($r('app.media.dragtoswitchpictures_drag_button'))
  .width($r('app.integer.dragtoswitchpictures_drag_button_image_width'))
  .height($r('app.integer.dragtoswitchpictures_decoration_height'))
  .draggable(false)
  .gesture( // TODO: 知識點:拖動手勢事件設置一個手指,滑動的最小距離設置為1vp,實現滑動時按鈕跟手動效。
    PanGesture({ fingers: CONFIGURATION.PANGESTURE_FINGERS, distance: CONFIGURATION.PANGESTURE_DISTANCE })
      .onActionStart(() => {
        this.dragRefOffset = CONFIGURATION.INIT_VALUE; // 每次拖動開始時將圖標拖動的距離初始化。
      })
      // TODO: 性能知識點: 該函數是系統高頻回調函數,避免在函數中進行冗余或耗時操作,例如應該減少或避免在函數打印日志,會有較大的性能損耗。
      .onActionUpdate((event: GestureEvent) => {
        // 通過監聽GestureEvent事件,實時監聽圖標拖動距離
        this.dragRefOffset = event.offsetX;
        this.leftImageWidth = this.imageWidth + this.dragRefOffset;
        this.rightImageWidth = CONFIGURATION.IMAGE_FULL_SIZE - this.leftImageWidth;
        if (this.leftImageWidth >= CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE) { // 當leftImageWidth大于等于310vp時,設置左右Image為固定值,實現停止滑動效果。
          this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE;
          this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_RIGHT_LIMIT_SIZE;
        } else if (this.leftImageWidth <= CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE) { // 當leftImageWidth小于等于30vp時,設置左右Image為固定值,實現停止滑動效果。
          this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE;
          this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_LEFT_LIMIT_SIZE;
        }
      })
      .onActionEnd((event: GestureEvent) => {
        if (this.leftImageWidth <= CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE) {
          this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE;
          this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_LEFT_LIMIT_SIZE;
          this.imageWidth = CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE;
        } else if (this.leftImageWidth >= CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE) {
          this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE;
          this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_RIGHT_LIMIT_SIZE;
          this.imageWidth = CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE;
        } else {
          this.leftImageWidth = this.imageWidth + this.dragRefOffset; // 滑動結束時leftImageWidth等于左邊原有Width+拖動距離。
          this.rightImageWidth = CONFIGURATION.IMAGE_FULL_SIZE - this.leftImageWidth; // 滑動結束時rightImageWidth等于340-leftImageWidth。
          this.imageWidth = this.leftImageWidth; // 滑動結束時ImageWidth等于leftImageWidth。
        }
      })
  )

工程結構&模塊類型

   dragtoswitchpictures                             // har包
   |---common
   |   |---Constants.ets                            // 常量類
   |---data
   |   |---DragToSwitchPicturesData.ets             // 生成模擬數據
   |---datasource
   |   |---BasicDataSource.ets                      // Basic數據控制器
   |   |---DragToSwitchPicturesDataSource.ets       // 左右拖動切換圖片數據控制器
   |---mainpage
   |   |---DragToSwitchPictures.ets                 // 主頁面
   |---model
   |   |---DragToSwitchPicturesModule.ets           // 左右拖動切換圖片數據模型
   |---view
   |   |---DragToSwitchPicturesView.ets             // 左右拖動切換圖片視圖
   |   |---DesignCattleView.ets                     // AI設計視圖
   |   |---TabsWaterFlowView.ets                    // 瀑布流嵌套Tabs視圖

寫在最后

如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙

  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待后續文章ing??,不定期分享原創知識。
  • 想要獲取更多完整鴻蒙最新學習知識點,請移步前往小編:https://gitee.com/MNxiaona/733GH/blob/master/jianshu
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容