HarmonyOS NEXT應(yīng)用開發(fā)之左右拖動切換圖片效果案例

介紹

本示例使用滑動手勢監(jiān)聽沙咏,實(shí)時調(diào)整左右兩側(cè)內(nèi)容顯示區(qū)域大小和效果。通過綁定gesture事件中的PanGesture平移手勢班套,實(shí)時獲取拖動距離肢藐。當(dāng)拖動時,實(shí)時地調(diào)節(jié)左右兩個Image組件的寬度吱韭,從而成功實(shí)現(xiàn)左右拖動切換圖片效果的功能吆豹。

效果圖預(yù)覽

使用說明

  1. 點(diǎn)擊中間按鈕進(jìn)行左右拖動切換圖片。

實(shí)現(xiàn)思路

本例涉及的關(guān)鍵特性和實(shí)現(xiàn)方案如下:

  1. 創(chuàng)建三個Stack組件理盆,用來展示裝修前后對比圖痘煤,第一個和第三個Stack分別存放裝修前的圖片和裝修后的圖片,zIndex設(shè)置為1猿规。第二個Stack存放按鈕的圖片衷快,zIndex設(shè)置為2,這樣按鈕的圖片就會覆蓋在兩張裝修圖片之上姨俩。 源碼參考DragToSwitchPicturesView.ets蘸拔。
Row() {
  Stack() {...}
  .zIndex(CONFIGURATION.ZINDEX1)
  .width(this.leftImageWidth) // z序設(shè)為1,為了使按鈕圖片浮在裝修圖片上环葵。

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

  Stack() {...}
  .zIndex(CONFIGURATION.ZINDEX1) // z序設(shè)為1张遭,為了使按鈕圖片浮在裝修圖片上陨晶。
  .width(this.rightImageWidth)
}
.justifyContent(FlexAlign.Center)
.width($r('app.string.full_size'))
  1. 將Image組件放在Row容器里,將Row容器的寬度設(shè)置為狀態(tài)變量帝璧,再利用clip屬性對于Row容器進(jìn)行裁剪。 源碼參考DragToSwitchPicturesView.ets湿刽。
Row() {
  Image($r('app.media.before_decoration'))
    .width($r('app.integer.decoration_width'))// Image的width固定的烁,Row的寬度變化,通過裁剪實(shí)現(xiàn)布局效果诈闺。
    .height($r('app.integer.decoration_height'))
    .draggable(false) // 設(shè)置Image不能拖動渴庆,不然長按Image會被拖動。
  }
  .width(this.leftImageWidth) // 將左側(cè)Row的width設(shè)置為leftImageWidth,這樣左側(cè)Row的width隨leftImageWidth的變化而變化襟雷。
  .clip(true) // clip屬性設(shè)置為true刃滓,裁剪超出Row寬度的圖片。
  .zIndex(CONFIGURATION.ZINDEX1) // z序設(shè)為1耸弄,為了使水印浮在裝修圖片上咧虎。
  .borderRadius({
    topLeft: $r('app.integer.borderradius'),
    bottomLeft: $r('app.integer.borderradius')
  }) // 將Row的左上角和左下角弧度設(shè)為10實(shí)現(xiàn)效果。
  1. 右邊的Image組件與左邊同樣的操作计呈,但是新增了一個direction屬性砰诵,使元素從右至左進(jìn)行布局,為的是讓Row從左側(cè)開始裁剪捌显。 源碼參考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序設(shè)為1,為了使水印浮在裝修圖片上扶歪。
// TODO: 知識點(diǎn):左邊Row使用clip時從右邊開始裁剪理肺,加了Direction.Rtl后,元素從右到左布局善镰,右邊Row使用clip時從左邊開始裁剪妹萨,這是實(shí)現(xiàn)滑動改變視圖內(nèi)容大小的關(guān)鍵。
.direction(Direction.Rtl)
.borderRadius({
 topRight: $r('app.integer.borderradius'),
 bottomRight: $r('app.integer.borderradius')
}) // 將Row的右上角和右下角弧度設(shè)為10實(shí)現(xiàn)效果媳禁。
  1. 中間的Image組件通過手勢事件中的滑動手勢對Image組件滑動進(jìn)行監(jiān)聽眠副,對左右Image組件的寬度進(jìn)行計(jì)算從而重新布局渲染。 源碼參考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: 知識點(diǎn):拖動手勢事件設(shè)置一個手指囱怕,滑動的最小距離設(shè)置為1vp,實(shí)現(xiàn)滑動時按鈕跟手動效毫别。
    PanGesture({ fingers: CONFIGURATION.PANGESTURE_FINGERS, distance: CONFIGURATION.PANGESTURE_DISTANCE })
      .onActionStart(() => {
        this.dragRefOffset = CONFIGURATION.INIT_VALUE; // 每次拖動開始時將圖標(biāo)拖動的距離初始化娃弓。
      })
      // TODO: 性能知識點(diǎn): 該函數(shù)是系統(tǒng)高頻回調(diào)函數(shù),避免在函數(shù)中進(jìn)行冗余或耗時操作岛宦,例如應(yīng)該減少或避免在函數(shù)打印日志台丛,會有較大的性能損耗。
      .onActionUpdate((event: GestureEvent) => {
        // 通過監(jiān)聽GestureEvent事件砾肺,實(shí)時監(jiān)聽圖標(biāo)拖動距離
        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) { // 當(dāng)leftImageWidth大于等于310vp時挽霉,設(shè)置左右Image為固定值,實(shí)現(xiàn)停止滑動效果变汪。
          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) { // 當(dāng)leftImageWidth小于等于30vp時侠坎,設(shè)置左右Image為固定值,實(shí)現(xiàn)停止滑動效果裙盾。
          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; // 滑動結(jié)束時leftImageWidth等于左邊原有Width+拖動距離实胸。
          this.rightImageWidth = CONFIGURATION.IMAGE_FULL_SIZE - this.leftImageWidth; // 滑動結(jié)束時rightImageWidth等于340-leftImageWidth他嫡。
          this.imageWidth = this.leftImageWidth; // 滑動結(jié)束時ImageWidth等于leftImageWidth。
        }
      })
  )

工程結(jié)構(gòu)&模塊類型

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

模塊依賴

routermodule

高性能知識點(diǎn)

本例使用了onActionUpdate函數(shù)庐完。該函數(shù)是系統(tǒng)高頻回調(diào)函數(shù)钢属,避免在函數(shù)中進(jìn)行冗余或耗時操作,例如應(yīng)該減少或避免在函數(shù)打印日志门躯,會有較大的性能損耗淆党。

本示例使用了LazyForEach進(jìn)行數(shù)據(jù)懶加載,WaterFlow布局時會根據(jù)可視區(qū)域按需創(chuàng)建FlowItem組件生音,并在FlowItem滑出可視區(qū)域外時銷毀以降低內(nèi)存占用宁否。

本示例使用了cachedCount設(shè)置預(yù)加載的FlowItem的數(shù)量,只在LazyForEach中生效缀遍,設(shè)置該屬性后會緩存cachedCount個FlowItem慕匠,LazyForEach超出顯示和緩存范圍的FlowItem會被釋放。

參考資料

LazyForEach:數(shù)據(jù)懶加載

Tabs

WaterFlow

ZIndex

PanGesture

clip

direction

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末域醇,一起剝皮案震驚了整個濱河市台谊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌譬挚,老刑警劉巖锅铅,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異减宣,居然都是意外死亡盐须,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門漆腌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贼邓,“玉大人,你說我怎么就攤上這事闷尿∷芫叮” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵填具,是天一觀的道長统舀。 經(jīng)常有香客問我,道長劳景,這世上最難降的妖魔是什么誉简? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮盟广,結(jié)果婚禮上闷串,老公的妹妹穿的比我還像新娘。我一直安慰自己衡蚂,他們只是感情好窿克,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著毛甲,像睡著了一般年叮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玻募,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天只损,我揣著相機(jī)與錄音,去河邊找鬼七咧。 笑死跃惫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的艾栋。 我是一名探鬼主播爆存,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蝗砾!你這毒婦竟也來了先较?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤悼粮,失蹤者是張志新(化名)和其女友劉穎闲勺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扣猫,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菜循,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了申尤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片癌幕。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瀑凝,靈堂內(nèi)的尸體忽然破棺而出序芦,到底是詐尸還是另有隱情,我是刑警寧澤粤咪,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布谚中,位于F島的核電站,受9級特大地震影響寥枝,放射性物質(zhì)發(fā)生泄漏宪塔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一囊拜、第九天 我趴在偏房一處隱蔽的房頂上張望某筐。 院中可真熱鬧,春花似錦冠跷、人聲如沸南誊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抄囚。三九已至霉赡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間幔托,已是汗流浹背穴亏。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留重挑,地道東北人嗓化。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像谬哀,于是被迫代替她去往敵國和親刺覆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容