99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

OpenHarmony實(shí)戰(zhàn)開(kāi)發(fā)-如何實(shí)現(xiàn)組件動(dòng)畫(huà)。

碼牛程序猿 ? 來(lái)源:jf_71304091 ? 作者:jf_71304091 ? 2024-04-28 15:49 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

ArkUI為組件提供了通用的屬性動(dòng)畫(huà)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)能力的同時(shí),還為一些組件提供了默認(rèn)的動(dòng)畫(huà)效果。例如,List的滑動(dòng)動(dòng)效,Button的點(diǎn)擊動(dòng)效,是組件自帶的默認(rèn)動(dòng)畫(huà)效果。在組件默認(rèn)動(dòng)畫(huà)效果的基礎(chǔ)上,開(kāi)發(fā)者還可以通過(guò)屬性動(dòng)畫(huà)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)對(duì)容器組件內(nèi)的子組件動(dòng)效進(jìn)行定制。

使用組件默認(rèn)動(dòng)畫(huà)

組件默認(rèn)動(dòng)效具備以下功能:

  • 提示用戶(hù)當(dāng)前狀態(tài),例如用戶(hù)點(diǎn)擊Button組件時(shí),Button組件默認(rèn)變灰,用戶(hù)即確定完成選中操作。
  • 提升界面精致程度和生動(dòng)性。
  • 減少開(kāi)發(fā)者工作量,例如列表滑動(dòng)組件自帶滑動(dòng)動(dòng)效,開(kāi)發(fā)者直接調(diào)用即可。

更多效果,可以參考組件說(shuō)明。

示例代碼和效果如下。

@Entry
@Component
struct ComponentDemo {
  build() {
    Row() {
      Checkbox({ name: 'checkbox1', group: 'checkboxGroup' })
        .select(true)
        .shape(CheckBoxShape.CIRCLE)
        .size({ width: 50, height: 50 })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}
ts

打造組件定制化動(dòng)效

部分組件支持通過(guò)屬性動(dòng)畫(huà)和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)自定義組件子Item的動(dòng)效,實(shí)現(xiàn)定制化動(dòng)畫(huà)效果。例如,Scroll組件中可對(duì)各個(gè)子組件在滑動(dòng)時(shí)的動(dòng)畫(huà)效果進(jìn)行定制。

  • 在滑動(dòng)或者點(diǎn)擊操作時(shí)通過(guò)改變各個(gè)Scroll子組件的仿射屬性來(lái)實(shí)現(xiàn)各種效果。
  • 如果要在滑動(dòng)過(guò)程中定制動(dòng)效,可在滑動(dòng)回調(diào)onScroll中監(jiān)控滑動(dòng)距離,并計(jì)算每個(gè)組件的仿射屬性。也可以自己定義手勢(shì),通過(guò)手勢(shì)監(jiān)控位置,手動(dòng)調(diào)用ScrollTo改變滑動(dòng)位置。
  • 在滑動(dòng)回調(diào)onScrollStop或手勢(shì)結(jié)束回調(diào)中對(duì)滑動(dòng)的最終位置進(jìn)行微調(diào)。

定制Scroll組件滑動(dòng)動(dòng)效示例代碼和效果如下。

import curves from '@ohos.curves';
import window from '@ohos.window';
import display from '@ohos.display';
import mediaquery from '@ohos.mediaquery';
import UIAbility from '@ohos.app.ability.UIAbility';

export default class GlobalContext extends AppStorage{
  static mainWin: window.Window|undefined = undefined;
  static mainWindowSize:window.Size|undefined = undefined;
}
/**
 * 窗口、屏幕相關(guān)信息管理類(lèi)
 */
export class WindowManager {
  private static instance: WindowManager|null = null;
  private displayInfo: display.Display|null = null;
  private orientationListener = mediaquery.matchMediaSync('(orientation: landscape)');

  constructor() {
    this.orientationListener.on('change', (mediaQueryResult: mediaquery.MediaQueryResult) = > { this.onPortrait(mediaQueryResult) })
    this.loadDisplayInfo()
  }

  /**
   * 設(shè)置主window窗口
   * @param win 當(dāng)前app窗口
   */
  setMainWin(win: window.Window) {
    if (win == null) {
      return
    }
    GlobalContext.mainWin = win;
    win.on("windowSizeChange", (data: window.Size) = > {
      if (GlobalContext.mainWindowSize == undefined || GlobalContext.mainWindowSize == null) {
        GlobalContext.mainWindowSize = data;
      } else {
        if (GlobalContext.mainWindowSize.width == data.width && GlobalContext.mainWindowSize.height == data.height) {
          return
        }
        GlobalContext.mainWindowSize = data;
      }

      let winWidth = this.getMainWindowWidth();
      AppStorage.setOrCreate< number >('mainWinWidth', winWidth)
      let winHeight = this.getMainWindowHeight();
      AppStorage.setOrCreate< number >('mainWinHeight', winHeight)
      let context:UIAbility = new UIAbility()
      context.context.eventHub.emit("windowSizeChange", winWidth, winHeight)
    })
  }

  static getInstance(): WindowManager {
    if (WindowManager.instance == null) {
      WindowManager.instance = new WindowManager();
    }
    return WindowManager.instance
  }

  private onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) {
    if (mediaQueryResult.matches == AppStorage.get< boolean >('isLandscape')) {
      return
    }
    AppStorage.setOrCreate< boolean >('isLandscape', mediaQueryResult.matches)
    this.loadDisplayInfo()
  }

  /**
   * 切換屏幕方向
   * @param ori 常量枚舉值:window.Orientation
   */
  changeOrientation(ori: window.Orientation) {
    if (GlobalContext.mainWin != null) {
      GlobalContext.mainWin.setPreferredOrientation(ori)
    }
  }

  private loadDisplayInfo() {
    this.displayInfo = display.getDefaultDisplaySync()
    AppStorage.setOrCreate< number >('displayWidth', this.getDisplayWidth())
    AppStorage.setOrCreate< number >('displayHeight', this.getDisplayHeight())
  }

  /**
   * 獲取main窗口寬度,單位vp
   */
  getMainWindowWidth(): number {
    return GlobalContext.mainWindowSize != null ? px2vp(GlobalContext.mainWindowSize.width) : 0
  }

  /**
   * 獲取main窗口高度,單位vp
   */
  getMainWindowHeight(): number {
    return GlobalContext.mainWindowSize != null ? px2vp(GlobalContext.mainWindowSize.height) : 0
  }

  /**
   * 獲取屏幕寬度,單位vp
   */
  getDisplayWidth(): number {
    return this.displayInfo != null ? px2vp(this.displayInfo.width) : 0
  }

  /**
   * 獲取屏幕高度,單位vp
   */
  getDisplayHeight(): number {
    return this.displayInfo != null ? px2vp(this.displayInfo.height) : 0
  }

  /**
   * 釋放資源
   */
  release() {
    if (this.orientationListener) {
      this.orientationListener.off('change', (mediaQueryResult: mediaquery.MediaQueryResult) = > { this.onPortrait(mediaQueryResult)})
    }
    if (GlobalContext.mainWin != null) {
      GlobalContext.mainWin.off('windowSizeChange')
    }
    WindowManager.instance = null;
  }
}

/**
 * 封裝任務(wù)卡片信息數(shù)據(jù)類(lèi)
 */
export class TaskData {
  bgColor: Color | string | Resource = Color.White;
  index: number = 0;
  taskInfo: string = 'music';

  constructor(bgColor: Color | string | Resource, index: number, taskInfo: string) {
    this.bgColor = bgColor;
    this.index = index;
    this.taskInfo = taskInfo;
  }
}

export const taskDataArr: Array< TaskData > =
  [
    new TaskData('#317AF7', 0, 'music'),
    new TaskData('#D94838', 1, 'mall'),
    new TaskData('#DB6B42 ', 2, 'photos'),
    new TaskData('#5BA854', 3, 'setting'),
    new TaskData('#317AF7', 4, 'call'),
    new TaskData('#D94838', 5, 'music'),
    new TaskData('#DB6B42', 6, 'mall'),
    new TaskData('#5BA854', 7, 'photos'),
    new TaskData('#D94838', 8, 'setting'),
    new TaskData('#DB6B42', 9, 'call'),
    new TaskData('#5BA854', 10, 'music')

  ];

@Entry
@Component
export struct TaskSwitchMainPage {
  displayWidth: number = WindowManager.getInstance().getDisplayWidth();
  scroller: Scroller = new Scroller();
  cardSpace: number = 0; // 卡片間距
  cardWidth: number = this.displayWidth / 2 - this.cardSpace / 2; // 卡片寬度
  cardHeight: number = 400; // 卡片高度
  cardPosition: Array< number > = []; // 卡片初始位置
  clickIndex: boolean = false;
  @State taskViewOffsetX: number = 0;
  @State cardOffset: number = this.displayWidth / 4;
  lastCardOffset: number = this.cardOffset;
  startTime: number|undefined=undefined

  // 每個(gè)卡片初始位置
  aboutToAppear() {
    for (let i = 0; i < taskDataArr.length; i++) {
      this.cardPosition[i] = i * (this.cardWidth + this.cardSpace);
    }
  }

  // 每個(gè)卡片位置
  getProgress(index: number): number {
    let progress = (this.cardOffset + this.cardPosition[index] - this.taskViewOffsetX + this.cardWidth / 2) / this.displayWidth;
    return progress
  }

  build() {
    Stack({ alignContent: Alignment.Bottom }) {
      // 背景
      Column()
        .width('100%')
        .height('100%')
        .backgroundColor(0xF0F0F0)

      // 滑動(dòng)組件
      Scroll(this.scroller) {
        Row({ space: this.cardSpace }) {
          ForEach(taskDataArr, (item:TaskData, index) = > {
            Column()
              .width(this.cardWidth)
              .height(this.cardHeight)
              .backgroundColor(item.bgColor)
              .borderStyle(BorderStyle.Solid)
              .borderWidth(1)
              .borderColor(0xAFEEEE)
              .borderRadius(15)
                // 計(jì)算子組件的仿射屬性
              .scale((this.getProgress(index) >= 0.4 && this.getProgress(index) <= 0.6) ?
                {
                  x: 1.1 - Math.abs(0.5 - this.getProgress(index)),
                  y: 1.1 - Math.abs(0.5 - this.getProgress(index))
                } :
                { x: 1, y: 1 })
              .animation({ curve: Curve.Smooth })
                // 滑動(dòng)動(dòng)畫(huà)
              .translate({ x: this.cardOffset })
              .animation({ curve: curves.springMotion() })
              .zIndex((this.getProgress(index) >= 0.4 && this.getProgress(index) <= 0.6) ? 2 : 1)
          }, (item:TaskData) = > item.toString())
        }
        .width((this.cardWidth + this.cardSpace) * (taskDataArr.length + 1))
        .height('100%')
      }
      .gesture(
        GestureGroup(GestureMode.Parallel,
          PanGesture({ direction: PanDirection.Horizontal, distance: 5 })
            .onActionStart((event: GestureEvent|undefined) = > {
              if(event){
                this.startTime = event.timestamp;
              }
            })
            .onActionUpdate((event: GestureEvent|undefined) = > {
              if(event){
                this.cardOffset = this.lastCardOffset + event.offsetX;
              }
            })
            .onActionEnd((event: GestureEvent|undefined) = > {
              if(event){
                let time = 0
                if(this.startTime){
                  time = event.timestamp - this.startTime;
                }
                let speed = event.offsetX / (time / 1000000000);
                let moveX = Math.pow(speed, 2) / 7000 * (speed > 0 ? 1 : -1);

                this.cardOffset += moveX;
                // 左滑大于最右側(cè)位置
                let cardOffsetMax = -(taskDataArr.length - 1) * (this.displayWidth / 2);
                if (this.cardOffset < cardOffsetMax) {
                  this.cardOffset = cardOffsetMax;
                }
                // 右滑大于最左側(cè)位置
                if (this.cardOffset > this.displayWidth / 4) {
                  this.cardOffset = this.displayWidth / 4;
                }

                // 左右滑動(dòng)距離不滿(mǎn)足/滿(mǎn)足切換關(guān)系時(shí),補(bǔ)位/退回
                let remainMargin = this.cardOffset % (this.displayWidth / 2);
                if (remainMargin < 0) {
                  remainMargin = this.cardOffset % (this.displayWidth / 2) + this.displayWidth / 2;
                }
                if (remainMargin <= this.displayWidth / 4) {
                  this.cardOffset += this.displayWidth / 4 - remainMargin;
                } else {
                  this.cardOffset -= this.displayWidth / 4 - (this.displayWidth / 2 - remainMargin);
                }

                // 記錄本次滑動(dòng)偏移量
                this.lastCardOffset = this.cardOffset;
              }
            })
        ), GestureMask.IgnoreInternal)
      .scrollable(ScrollDirection.Horizontal)
      .scrollBar(BarState.Off)

      // 滑動(dòng)到首尾位置
      Button('Move to first/last')
        .backgroundColor(0x888888)
        .margin({ bottom: 30 })
        .onClick(() = > {
          this.clickIndex = !this.clickIndex;

          if (this.clickIndex) {
            this.cardOffset = this.displayWidth / 4;
          } else {
            this.cardOffset = this.displayWidth / 4 - (taskDataArr.length - 1) * this.displayWidth / 2;
          }
          this.lastCardOffset = this.cardOffset;
        })
    }
    .width('100%')
    .height('100%')
  }
}
ts

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 組件
    +關(guān)注

    關(guān)注

    1

    文章

    532

    瀏覽量

    18419
  • 鴻蒙
    +關(guān)注

    關(guān)注

    60

    文章

    2617

    瀏覽量

    44033
  • OpenHarmony
    +關(guān)注

    關(guān)注

    29

    文章

    3851

    瀏覽量

    18587
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    HarmonyOS開(kāi)發(fā)案例:【購(gòu)物車(chē)app】

    OpenHarmony ArkUI框架提供了豐富的動(dòng)畫(huà)組件和接口,開(kāi)發(fā)者可以根據(jù)實(shí)際場(chǎng)景和開(kāi)發(fā)需求,選用豐富的
    的頭像 發(fā)表于 05-14 18:19 ?1473次閱讀
    HarmonyOS<b class='flag-5'>開(kāi)發(fā)</b>案例:【購(gòu)物車(chē)app】

    OpenHarmony實(shí)戰(zhàn)開(kāi)發(fā)-如何實(shí)現(xiàn)動(dòng)畫(huà)

    你們的 『點(diǎn)贊和評(píng)論』,才是我創(chuàng)造的動(dòng)力。 關(guān)注小編,同時(shí)可以期待后續(xù)文章ing?,不定期分享原創(chuàng)知識(shí)。 更多鴻蒙最新技術(shù)知識(shí)點(diǎn),請(qǐng)關(guān)注作者博客:鴻蒙實(shí)戰(zhàn)經(jīng)驗(yàn)分享:鴻蒙基礎(chǔ)入門(mén)開(kāi)發(fā)寶典! (qq.com)**
    發(fā)表于 05-06 14:11

    OpenHarmony實(shí)戰(zhàn)開(kāi)發(fā)-如何實(shí)現(xiàn)窗口開(kāi)發(fā)概述

    操作系統(tǒng)而言,窗口模塊提供了不同應(yīng)用界面的組織管理邏輯。 窗口模塊的用途 在OpenHarmony中,窗口模塊主要負(fù)責(zé)以下職責(zé): 提供應(yīng)用和系統(tǒng)界面的窗口對(duì)象。 應(yīng)用開(kāi)發(fā)者通過(guò)窗口加載UI界面,實(shí)現(xiàn)界面
    發(fā)表于 05-06 14:29

    HarmonyOS Lottie組件,讓動(dòng)畫(huà)繪制更簡(jiǎn)單

    了豐富的API,讓開(kāi)發(fā)者能輕松控制動(dòng)畫(huà),大大提高了開(kāi)發(fā)效率。 二、Lottie實(shí)戰(zhàn) 通過(guò)上文對(duì)Lottie的介紹,相信很多小伙伴已經(jīng)感受到了Lottie
    發(fā)表于 02-22 14:55

    OpenHarmony標(biāo)準(zhǔn)設(shè)備應(yīng)用開(kāi)發(fā)筆記匯總

    如何在標(biāo)準(zhǔn)設(shè)備上運(yùn)行一個(gè)最簡(jiǎn)單的 OpenHarmony 程序。2、如何在OpenHarmony實(shí)現(xiàn)音樂(lè)的播放本章是 OpenHarmony 標(biāo)準(zhǔn)設(shè)備應(yīng)用
    發(fā)表于 03-28 14:19

    OpenHarmony標(biāo)準(zhǔn)設(shè)備應(yīng)用開(kāi)發(fā)(二)——布局、動(dòng)畫(huà)與音樂(lè)

    節(jié)的基礎(chǔ)上,學(xué)到更多 ArkUI 組件和布局在 OpenHarmony 中的應(yīng)用,以及如何在自己的應(yīng)用中實(shí)現(xiàn)顯示動(dòng)畫(huà)的效果。代碼鏈接:https://gitee.com/
    發(fā)表于 04-07 17:09

    OpenHarmony有氧拳擊之應(yīng)用端開(kāi)發(fā)

    變化的動(dòng)畫(huà),便很適合使用屬性動(dòng)畫(huà)來(lái)實(shí)現(xiàn)。屬性動(dòng)畫(huà)是指組件的通用屬性發(fā)生變化時(shí),會(huì)根據(jù)開(kāi)始狀態(tài)和通用屬性改變后的狀態(tài)作為
    發(fā)表于 10-09 15:19

    HarmonyOS/OpenHarmony應(yīng)用開(kāi)發(fā)-屬性動(dòng)畫(huà)

    組件的某些通用屬性變化時(shí),可以通過(guò)屬性動(dòng)畫(huà)實(shí)現(xiàn)漸變過(guò)渡效果,提升用戶(hù)體驗(yàn)。支持的屬性包括width、height、backgroundColor、opacity、scale、rotate
    發(fā)表于 01-03 10:51

    OpenHarmony應(yīng)用開(kāi)發(fā)—ArkUI組件集合

    頁(yè)面 接口參考:@ohos.curves, @ohos.router 顯示動(dòng)畫(huà) 用到全局組件TitleBar,IntroductionTitle實(shí)現(xiàn)頁(yè)面 接口參考:animateTo 屬性
    發(fā)表于 09-22 14:56

    基于openharmony適配移植的多種動(dòng)畫(huà)效果實(shí)現(xiàn)教程

    項(xiàng)目介紹 項(xiàng)目名稱(chēng): OhosLoadingAnimation 所屬系列:openharmony的第三方組件適配移植 功能:實(shí)現(xiàn)多種動(dòng)畫(huà)效果 項(xiàng)目移植狀態(tài):主功能完成 調(diào)用差異
    發(fā)表于 04-02 10:55 ?0次下載

    openharmony第三方組件適配移植的動(dòng)畫(huà)庫(kù)實(shí)現(xiàn)

    項(xiàng)目介紹 項(xiàng)目名稱(chēng):CanAnimation 所屬系列:openharmony的第三方組件適配移植 功能:使用openharmony屬性動(dòng)畫(huà)寫(xiě)的一個(gè)庫(kù),可組建
    發(fā)表于 04-02 11:30 ?3次下載

    openharmony第三方組件適配移植的SVGA動(dòng)畫(huà)渲染庫(kù)

    項(xiàng)目介紹 項(xiàng)目名稱(chēng):SVGAPlayer-Ohos 所屬系列:openharmony的第三方組件適配移植 功能:SVGAPlayer-Ohos 是一個(gè)輕量的動(dòng)畫(huà)渲染庫(kù)。你可以使用工具從 Adobe
    發(fā)表于 04-02 11:47 ?15次下載

    OpenHarmony技術(shù)論壇:傳統(tǒng)動(dòng)畫(huà)實(shí)現(xiàn)的不足

    OpenHarmony技術(shù)論壇:流暢動(dòng)畫(huà)可傳統(tǒng)動(dòng)畫(huà)實(shí)現(xiàn)的不足。
    的頭像 發(fā)表于 04-25 14:21 ?1288次閱讀
    <b class='flag-5'>OpenHarmony</b>技術(shù)論壇:傳統(tǒng)<b class='flag-5'>動(dòng)畫(huà)</b><b class='flag-5'>實(shí)現(xiàn)</b>的不足

    2022 OpenHarmony組件大賽,共建開(kāi)源組件

    原標(biāo)題:共建開(kāi)源組件生態(tài) 2022 OpenHarmony組件大賽等你來(lái) 2022年4月15日,2022 OpenHarmony組件大賽(下
    的頭像 發(fā)表于 04-26 17:31 ?1759次閱讀
    2022 <b class='flag-5'>OpenHarmony</b><b class='flag-5'>組件</b>大賽,共建開(kāi)源<b class='flag-5'>組件</b>

    OpenHarmony輕量系統(tǒng)書(shū)籍推薦《OpenHarmony輕量設(shè)備開(kāi)發(fā)理論與實(shí)戰(zhàn)

    最近大家問(wèn)的智能家居套件方面有沒(méi)有可以參考的資料,這里給大家統(tǒng)一回復(fù)一下 推薦大家可以看這本書(shū) 《OpenHarmony輕量設(shè)備開(kāi)發(fā)理論與實(shí)戰(zhàn)》 本書(shū)系統(tǒng)地講授OpenHarmony
    的頭像 發(fā)表于 07-20 12:43 ?1767次閱讀