想了解更多關于開源的內容,請訪問:
51CTO 鴻蒙開發者社區
https://ost.51cto.com
本示例使用滑動手勢監聽,實時調整左右兩側內容顯示區域大小和效果。通過綁定gesture事件中的PanGesture平移手勢,實時獲取拖動距離。當拖動時,實時地調節左右兩個Image組件的寬度,從而成功實現左右拖動切換圖片效果的功能。
點擊中間按鈕進行左右拖動切換圖片。
本例涉及的關鍵特性和實現方案如下:
創建三個Stack組件,用來展示裝修前后對比圖,第一個和第三個Stack分別存放裝修前的圖片和裝修后的圖片,zIndex設置為1。第二個Stack存放按鈕的圖片,zIndex設置為2,這樣按鈕的圖片就會覆蓋在兩張裝修圖片之上。
源碼參考DragToSwitchPicturesView.ets。
Row() { Stack() {...} .zIndex(CONFIGURATION.ZINDEX1) .width(this.leftImageWidth) // z序設為1,為了使按鈕圖片浮在裝修圖片上。 Stack() {...} .width($r('app.integer.drag_button_stack_width')) .zIndex(CONFIGURATION.ZINDEX2) // z序設為2,為了使按鈕圖片浮在裝修圖片上。 Stack() {...} .zIndex(CONFIGURATION.ZINDEX1) // z序設為1,為了使按鈕圖片浮在裝修圖片上。 .width(this.rightImageWidth)}.justifyContent(FlexAlign.Center).width($r('app.string.full_size'))
將Image組件放在Row容器里,將Row容器的寬度設置為狀態變量,再利用clip屬性對于Row容器進行裁剪。
源碼參考DragToSwitchPicturesView.ets。
Row() { Image($r('app.media.before_decoration')) .width($r('app.integer.decoration_width'))// Image的width固定,Row的寬度變化,通過裁剪實現布局效果。 .height($r('app.integer.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.borderradius'), bottomLeft: $r('app.integer.borderradius') }) // 將Row的左上角和左下角弧度設為10實現效果。
右邊的Image組件與左邊同樣的操作,但是新增了一個direction屬性,使元素從右至左進行布局,為的是讓Row從左側開始裁剪。
源碼參考DragToSwitchPicturesView.ets。
Row() { Image($r('app.media.after_decoration')) .width($r('app.integer.decoration_width')) .height($r('app.integer.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.borderradius'), bottomRight: $r('app.integer.borderradius')}) // 將Row的右上角和右下角弧度設為10實現效果。
中間的Image組件通過手勢事件中的滑動手勢對Image組件滑動進行監聽,對左右Image組件的寬度進行計算從而重新布局渲染。
源碼參考DragToSwitchPicturesView.ets。
Image($r('app.media.drag_button')) .width($r('app.integer.drag_button_image_width')) .height($r('app.integer.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視圖
routermodule
本例使用了onActionUpdate函數。該函數是系統高頻回調函數,避免在函數中進行冗余或耗時操作,例如應該減少或避免在函數打印日志,會有較大的性能損耗。
本示例使用了LazyForEach進行數據懶加載,WaterFlow布局時會根據可視區域按需創建FlowItem組件,并在FlowItem滑出可視區域外時銷毀以降低內存占用。
本示例使用了cachedCount設置預加載的FlowItem的數量,只在LazyForEach中生效,設置該屬性后會緩存cachedCount個FlowItem,LazyForEach超出顯示和緩存范圍的FlowItem會被釋放。
想了解更多關于開源的內容,請訪問:
51CTO 鴻蒙開發者社區
https://ost.51cto.com
本文鏈接:http://www.www897cc.com/showinfo-26-76513-0.html左右拖動切換圖片效果案例
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com