成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

控制頁面刷新范圍(OpenHarmony)

系統 OpenHarmony
根據業務需要,有時我們需要觸發單個組件的狀態更新,有時需要觸發部分或全部組件的狀態更新。那么如何控制組件狀態刷新的范圍呢?本例將為大家提供一種參考方案。

想了解更多關于開源的內容,請訪問:

51CTO 開源基礎軟件社區

https://ost.51cto.com

場景說明

在實現頁面UI時,業務方需要根據業務邏輯動態更新組件的狀態,常見的如在手機桌面長按某個App的圖標時,圖標背景色、大小等會發生變化。根據業務需要,有時我們需要觸發單個組件的狀態更新,有時需要觸發部分或全部組件的狀態更新。那么如何控制組件狀態刷新的范圍呢?本例將為大家提供一種參考方案。

效果呈現

本例最終效果如下:

控制頁面刷新范圍(OpenHarmony)-開源基礎軟件社區

運行環境

本例基于以下環境開發,開發者也可以基于其他適配的版本進行開發:

  • IDE: DevEco Studio 3.1 Release
  • SDK: Ohos_sdk_public 3.2.12.5(API Version 9 Release)

實現思路

ArkUI可以通過頁面的狀態數據驅動UI的更新,其UI更新機制可以通過如下表達式來體現:

UI=f(state)

用戶構建了UI模型,其中參數state代表頁面組件的運行時狀態。當state改變時,UI作為返回結果,也將進行對應的改變刷新。f作為狀態管理機制,維護組件運行時的狀態變化所帶來的UI重新渲染。組件的狀態改變可通過狀態變量進行控制。

基于上述理論,如果要控制頁面的更新范圍,我們必須要:定義準確狀態變量,并控制狀態變量影響的組件范圍。

本例中包含8個APP圖標,其中涉及5種狀態變化,按照局部刷新和全局刷新可分為:

  • 局部刷新(單個卡片變化)
  • 點擊卡片,卡片背景色變為紅色。
  • 點擊卡片,卡片進行縮放。
  • 拖拽卡片,卡片位置變化。
  • 全局刷新(全部卡片變化)
  • 長按某個卡片,為所有卡片添加刪除圖標。
  • 點擊刪除圖標外的任意地方,刪除圖標消失。

所以處理思路為,控制局部刷新的狀態變量在子組件中定義,綁定子組件,控制全局刷新的狀態變量在父組件中進行定義,并由父組件傳遞給所有子組件。如下圖:

控制頁面刷新范圍(OpenHarmony)-開源基礎軟件社區

開發步驟

由于本例重點講解刷新區域的控制,所以開發步驟會著重講解相關實現,不相關的內容不做介紹,全量代碼可參考完整代碼章節。

創建APP卡片組件作為子組件,每個卡片包含文本和刪除圖標。
具體代碼如下:

@Component
export struct AppItem {
  ...
  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      Image($r('app.media.ic_public_close'))
        .height(30)
        .width(30)
        .zIndex(2)
        .offset({
          x: -12,
          y: 12
        })
      Text(this.data.title)
        .width(100)
        .height(100)
        .fontSize(16)
        .margin(10)
        .textAlign(TextAlign.Center)
        .borderRadius(10)
    }   
  }
}

創建父組件,并在父組件中引用子組件。
具體代碼如下:

@Entry
@Component
struct Sample {
  ...
  build() {
    Stack({ alignContent: Alignment.Bottom }) {
      Flex({ wrap: FlexWrap.Wrap }) {
        // 通過循環渲染加載所有子組件
        ForEach(this.items, (item: ItemProps, index: number) => {
          // 引用App卡片子組件
          AppItem({data: this.items[index]})
        }, (item: ItemProps) => item.id.toString())
      }
      .width('100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ffffff')
    .margin({ top:50 })
  }
}

由于卡片背景色變化、卡片縮放、卡片拖拽在觸發時都是針對單個卡片的狀態變化,所以在卡片子組件中定義相應的狀態變量,用來控制單個卡片的狀態變化。
本例中定義狀態變量“data”用來控制卡片拖拽時位置的刷新;定義狀態變量”downFlag“用來監聽卡片是否被按下,從而控制卡片背景色及縮放狀態的更新。
具體代碼如下:

@Component
export struct AppItem {
  // 定義狀態變量data,用來控制卡片被拖拽時位置的刷新
  @State data: ItemProps = {};
  // 定義狀態變量downFlag用來監聽卡片是否被按下,從而控制卡片背景色及縮放狀態的更新
  @State downFlag: boolean = false;
  ...
  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      Image($r('app.media.ic_public_close'))
            .height(30)
            .width(30)
            .zIndex(2)
            .offset({
              x: -12,
              y: 12
            })
      Text(this.data.title)
        .width(100)
        .height(100)
        .fontSize(16)
        .margin(10)
        .textAlign(TextAlign.Center)
        .borderRadius(10)
        // 根據狀態變量downFlag的變化,更新背景色
        .backgroundColor(this.downFlag ? '#EEA8AB' : '#86C7CC')
        // 背景色更新時添加屬性動畫
        .animation({
          duration: 500,
          curve: Curve.Friction
        })
        // 綁定onTouch事件,監聽卡片是否被按下,根據不同狀態改變downFlag的值
        .onTouch((event: TouchEvent) => {
          if (event.type == TouchType.Down) {
            this.downFlag = true
          } else if (event.type == TouchType.Up) { 
            this.downFlag = false
          }
        })
    }
    // 根據狀態變量downFlag的變化,控制卡片的縮放
    .scale(this.downFlag ? { x: 0.8, y: 0.8 } : { x: 1, y: 1 })
    // 通過狀態變量data的變化,控制卡片位置的更新
    .offset({
      x: this.data.offsetX,
      y: this.data.offsetY
    })
    // 拖動觸發該手勢事件
    .gesture(
      GestureGroup(GestureMode.Parallel,
        ...
        PanGesture(this.panOption)
          .onActionStart((event: GestureEvent) => {
            console.info('Pan start')
          })
          // 拖動卡片時,改變狀態變量data的值
          .onActionUpdate((event: GestureEvent) => {
            this.data.offsetX = this.data.positionX + event.offsetX
            this.data.offsetY = this.data.positionY + event.offsetY
          })
          .onActionEnd(() => {
            this.data.positionX = this.data.offsetX
            this.data.positionY = this.data.offsetY
            console.info('Pan end')
          })
      )
    )
  }
}

長按卡片,卡片右上角會出現刪除圖標。

由于所有卡片右上角都會出現刪除圖標,所以這里需要做全局的刷新。本例在父組件中定義狀態變量“deleteVisibility”,在調用子組件時,將其作為參數傳遞給所有卡片子組件,并且通過@Link裝飾器與子組件進行雙向綁定,從而可以控制所有卡片子組件中刪除圖標的更新。

父組件代碼:

@Entry
@Component
struct Sample {
  ...
  // 定義狀態變量deleteVisibility,控制App卡片上刪除圖標的更新
  @State deleteVisibility: boolean = false
  ...
  build() {
    Stack({ alignContent: Alignment.Bottom }) {
      Flex({ wrap: FlexWrap.Wrap }) {
        // 通過循環渲染加載所有子組件
        ForEach(this.items, (item: ItemProps, index: number) => {
          // 將狀態變量deleteVisibility傳遞給每一個子組件,從而deleteVisibility變化時可以觸發所有子組件的更新
          AppItem({ deleteVisibility: $deleteVisibility, data: this.items[index], onDeleteClick: this.delete })
        }, (item: ItemProps) => item.id.toString())
      }
      .width('100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ffffff')
    .margin({ top:50 })
    .onClick(() => {
      this.deleteVisibility = false
    })
  }

子組件代碼:

@Component
export struct AppItem {
  ...
  // 定義deleteVisibility狀態變量,并通過@Link裝飾器與父組件中的同名變量雙向綁定,該變量值發生變化時父子組件可雙向同步
  @Link deleteVisibility: boolean;
  ...
  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      // 通過deleteVisibility控制刪除圖標的隱藏和顯示,當deleteVisibility值為true時顯示,為false時隱藏
      if(this.deleteVisibility){
        Image($r('app.media.ic_public_close'))
          .height(30)
          .width(30)
          .zIndex(2)
          // 控制刪除圖標的顯隱
          .visibility(Visibility.Visible)
          .offset({
            x: -12,
            y: 12
          })
          .onClick(() => this.onDeleteClick(this.data.id))
      }else{
        Image($r('app.media.ic_public_close'))
          .height(30)
          .width(30)
          .zIndex(2)
          .visibility(Visibility.Hidden)
          .offset({
            x: -12,
            y: 12
          })
          .onClick(() => this.onDeleteClick(this.data.id))
      }
    ...
    .gesture(
      GestureGroup(GestureMode.Parallel,
        // 識別長按手勢
        LongPressGesture({ repeat: true })
          .onAction((event: GestureEvent) => {
            if (event.repeat) {
              // 長按時改變deleteVisibility的值為true,從而更新刪除圖標為顯示狀態
              this.deleteVisibility = true
            }
            console.info('LongPress onAction')
          }),
        ...
      )
    )
  }
}

完整代碼

本例完整代碼如下:
data.ets文件(數據模型文件)

// data.ets
// AppItem組件接口信息
export interface ItemProps {
  id?: number,
  title?: string,
  offsetX?: number, // X偏移量
  offsetY?: number, // Y偏移量
  positionX?: number, // 在X的位置
  positionY?: number, // 在Y的位置
}

// AppItem初始數據
export const initItemsData: ItemProps[] = [
  {
    id: 1,
    title: 'APP1',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 2,
    title: 'APP2',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 3,
    title: 'APP3',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 4,
    title: 'APP4',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 5,
    title: 'APP5',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 6,
    title: 'APP6',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 7,
    title: 'APP7',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
  {
    id: 8,
    title: 'APP8',
    offsetX: 0,
    offsetY: 0,
    positionX: 0,
    positionY: 0
  },
]

AppItem.ets文件(卡片子組件)

// AppItem.ets
import { ItemProps } from '../model/data';

@Component
export struct AppItem {
  // 定義狀態變量data,用來控制卡片被拖拽時位置的刷新
  @State data: ItemProps = {};
  // 定義狀態變量downFlag用來監聽卡片是否被按下,從而控制卡片背景色及縮放狀態的更新
  @State downFlag: boolean = false;
  // 定義deleteVisibility狀態變量,并通過@Link裝飾器與父組件中的同名變量雙向綁定,該變量值發生變化時父子組件可雙向同步
  @Link deleteVisibility: boolean;

  private onDeleteClick: (id: number) => void;
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All });
  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      // 通過deleteVisibility控制刪除圖標的隱藏和顯示,當deleteVisibility值為true時顯示,為false時隱藏
      if(this.deleteVisibility){
        Image($r('app.media.ic_public_close'))
          .height(30)
          .width(30)
          .zIndex(2)
          // 控制刪除圖標的顯隱
          .visibility(Visibility.Visible)
          .offset({
            x: -12,
            y: 12
          })
          .onClick(() => this.onDeleteClick(this.data.id))
      }else{
        Image($r('app.media.ic_public_close'))
          .height(30)
          .width(30)
          .zIndex(2)
          .visibility(Visibility.Hidden)
          .offset({
            x: -12,
            y: 12
          })
          .onClick(() => this.onDeleteClick(this.data.id))
      }

      Text(this.data.title)
        .width(100)
        .height(100)
        .fontSize(16)
        .margin(10)
        .textAlign(TextAlign.Center)
        .borderRadius(10)
        // 根據狀態變量downFlag的變化,更新背景色
        .backgroundColor(this.downFlag ? '#EEA8AB' : '#86C7CC')
        // 背景色更新時添加屬性動畫
        .animation({
          duration: 500,
          curve: Curve.Friction
        })
        // 綁定onTouch事件,監聽卡片是否被按下,根據不同狀態改變downFlag的值
        .onTouch((event: TouchEvent) => {
          if (event.type == TouchType.Down) {
            this.downFlag = true
          } else if (event.type == TouchType.Up) { // 手指抬起
            this.downFlag = false
          }
        })
    }
    // 根據狀態變量downFlag的變化,控制卡片的縮放
    .scale(this.downFlag ? { x: 0.8, y: 0.8 } : { x: 1, y: 1 })
    // 通過狀態變量data的變化,控制卡片位置的更新
    .offset({
      x: this.data.offsetX,
      y: this.data.offsetY
    })
    // 拖動觸發該手勢事件
    .gesture(
      GestureGroup(GestureMode.Parallel,
        // 識別長按手勢
        LongPressGesture({ repeat: true })
          .onAction((event: GestureEvent) => {
            if (event.repeat) {
              // 長按時改變deleteVisibility的值為true,從而更新刪除圖標為顯示狀態
              this.deleteVisibility = true
            }
            console.info('LongPress onAction')
          }),
        PanGesture(this.panOption)
          .onActionStart((event: GestureEvent) => {
            console.info('Pan start')
          })
          // 拖動卡片時,改變狀態變量data的值
          .onActionUpdate((event: GestureEvent) => {
            this.data.offsetX = this.data.positionX + event.offsetX
            this.data.offsetY = this.data.positionY + event.offsetY
          })
          .onActionEnd(() => {
            this.data.positionX = this.data.offsetX
            this.data.positionY = this.data.offsetY
            console.info('Pan end')
          })
      )
    )
  }
}

Index.ets文件(父組件)

// Index.ets
import { AppItem } from '../components/MyItem';
import { initItemsData } from '../model/data';
import { ItemProps } from '../model/data';

@Entry
@Component
struct Sample {
  @State items: ItemProps[] = [];
  // 定義狀態變量deleteVisibility,控制App卡片上刪除圖標的更新
  @State deleteVisibility: boolean = false

  // 刪除指定id組件
  private delete = (id: number) => {
    const index = this.items.findIndex(item => item.id === id);
    this.items.splice(index, 1);
  }

  // 生命周期函數:組件即將出現時調用
  aboutToAppear() {
    this.items = [...initItemsData];
  }

  build() {
    Stack({ alignContent: Alignment.Bottom }) {
      Flex({ wrap: FlexWrap.Wrap }) {
        // 通過循環渲染加載所有子組件
        ForEach(this.items, (item: ItemProps, index: number) => {
          // 將狀態變量deleteVisibility傳遞給每一個子組件,從而deleteVisibility變化時可以觸發所有子組件的更新
          AppItem({ deleteVisibility: $deleteVisibility, data: this.items[index], onDeleteClick: this.delete })
        }, (item: ItemProps) => item.id.toString())
      }
      .width('100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ffffff')
    .margin({ top:50 })
    .onClick(() => {
      // 點擊組件,deleteVisibility值變為false,從而隱藏所有卡片的刪除圖標
      this.deleteVisibility = false
    })
  }
}

總結

刷新范圍一般通過狀態變量進行控制,需要厘清狀態變量影響的范圍,從而當狀態變量發生改變時可同步刷新相關的UI區域。

想了解更多關于開源的內容,請訪問:

51CTO 開源基礎軟件社區

https://ost.51cto.com

責任編輯:jianghua 來源: 51CTO 開源基礎軟件社區
相關推薦

2012-05-22 11:15:37

jQuery

2021-03-12 16:25:17

技巧vue頁面刷新

2023-09-14 15:49:42

PWM鴻蒙

2023-09-06 15:35:14

2012-08-14 14:00:21

JavaScript

2017-10-17 15:40:25

javascript刷新頁面

2023-08-07 15:23:28

鴻蒙首次啟動申請授權

2015-05-13 09:36:18

js模擬手機下拉刷新

2015-03-26 13:14:53

javascriptjs callback實現調用

2009-07-31 08:56:59

ASP.NET頁面刷新

2018-07-16 15:17:49

2023-07-31 17:35:31

ArkTS鴻蒙

2023-08-09 14:43:42

應用開發ArkTS

2024-11-26 11:59:06

2022-08-05 19:37:59

鴻蒙Api框架

2022-06-01 22:35:25

滑桿組件鴻蒙

2022-01-07 09:56:16

鴻蒙HarmonyOS應用

2023-09-13 15:33:57

I2C鴻蒙

2012-03-02 09:37:53

Ajax
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩一区在线观看视频 | 综合激情久久 | 国产精品国产精品国产专区不蜜 | 欧美一区二区在线观看 | 国产精品精品视频一区二区三区 | 一区二区视频在线 | 一级黄色绿像片 | 在线观看电影av | 99九九视频 | www国产成人免费观看视频,深夜成人网 | 日韩av成人 | 国产三级大片 | 国产精品视频在线播放 | 中文字幕精品视频 | 我想看国产一级毛片 | 日本三级电影在线免费观看 | 久草精品视频 | 欧美日韩国产欧美 | 国产一区二区在线免费播放 | 波多野结衣精品 | 91av在线免费播放 | 香蕉久久久久久 | 奇米av | 日韩二 | 欧洲精品码一区二区三区免费看 | 日韩免费在线 | 精品欧美一区二区三区 | 国产精品一区二区三区久久久 | 国产精品免费一区二区三区四区 | 91玖玖 | 国产视频在线一区二区 | 北条麻妃av一区二区三区 | 女同久久另类99精品国产 | 日韩成人在线观看 | 91欧美精品成人综合在线观看 | 在线一区| 成人水多啪啪片 | 一道本在线 | 精品国产乱码久久久久久蜜柚 | 中文在线视频 | xx视频在线观看 |