首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发三

  • 25-02-15 05:41
  • 2738
  • 11115
blog.csdn.net

目录

1 -> 绘制图形

1.1 -> 绘制基本几何图形

1.2 -> 绘制自定义几何图形

2 -> 添加动画效果

2.1 -> animateTo实现闪屏动画

2.2 -> 页面转场动画

3 -> 常见组件说明


1 -> 绘制图形

绘制能力主要是通过框架提供的绘制组件来支撑,支持svg标准绘制命令。

1.1 -> 绘制基本几何图形

绘制组件封装了一些常见的基本几何图形,比如矩形Rect、圆形Circle、椭圆形Ellipse等,为开发者省去了路线计算的过程。

FoodDetail页面的食物成分表里,给每一项成分名称前都加上一个圆形的图标作为成分标签。

1. 创建Circle组件,在每一项含量成分前增加一个圆形图标作为标签。设置Circle的直径为 6vp。修改FoodDetail页面的ContentTable组件里的IngredientItem方法,在成分名称前添加Circle。

  1. // FoodDetail.ets
  2. @Component
  3. struct ContentTable {
  4. private foodItem: FoodData
  5. @Builder IngredientItem(title:string, colorValue: string, name: string, value: string) {
  6. Flex() {
  7. Text(title)
  8. .fontSize(17.4)
  9. .fontWeight(FontWeight.Bold)
  10. .layoutWeight(1)
  11. Flex({ alignItems: ItemAlign.Center }) {
  12. Circle({width: 6, height: 6})
  13. .margin({right: 12})
  14. .fill(colorValue)
  15. Text(name)
  16. .fontSize(17.4)
  17. .flexGrow(1)
  18. Text(value)
  19. .fontSize(17.4)
  20. }
  21. .layoutWeight(2)
  22. }
  23. }
  24. build() {
  25. ......
  26. }
  27. }

2. 每个成分的标签颜色不一样,所以我们在build方法中,调用IngredientItem,给每个Circle填充不一样的颜色。

  1. // FoodDetail.ets
  2. @Component
  3. struct ContentTable {
  4. private foodItem: FoodData
  5. @Builder IngredientItem(title:string, colorValue: string, name: string, value: string) {
  6. Flex() {
  7. Text(title)
  8. .fontSize(17.4)
  9. .fontWeight(FontWeight.Bold)
  10. .layoutWeight(1)
  11. Flex({ alignItems: ItemAlign.Center }) {
  12. Circle({width: 6, height: 6})
  13. .margin({right: 12})
  14. .fill(colorValue)
  15. Text(name)
  16. .fontSize(17.4)
  17. .flexGrow(1)
  18. Text(value)
  19. .fontSize(17.4)
  20. }
  21. .layoutWeight(2)
  22. }
  23. }
  24. build() {
  25. Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {
  26. this.IngredientItem('Calories', '#FFf54040', 'Calories', this.foodItem.calories + 'kcal')
  27. this.IngredientItem('Nutrition', '#FFcccccc', 'Protein', this.foodItem.protein + 'g')
  28. this.IngredientItem(' ', '#FFf5d640', 'Fat', this.foodItem.fat + 'g')
  29. this.IngredientItem(' ', '#FF9e9eff', 'Carbohydrates', this.foodItem.carbohydrates + 'g')
  30. this.IngredientItem(' ', '#FF53f540', 'VitaminC', this.foodItem.vitaminC + 'mg')
  31. }
  32. .height(280)
  33. .padding({ top: 30, right: 30, left: 30 })
  34. }
  35. }

1.2 -> 绘制自定义几何图形

除绘制基础几何图形,开发者还可以使用Path组件来绘制自定义的路线,下面进行绘制应用的Logo图案。

1. 在pages文件夹下创建新的页面Logo.ets。

2. Logo.ets中删掉模板代码,创建Logo Component。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. build() {
  5. }
  6. }

3. 创建Flex组件为根节点,宽高设置为100%,设置其在主轴方向和交叉轴方向的对齐方式都为Center,创建Shape组件为Flex子组件。

Shape组件是所有绘制组件的父组件。如果需要组合多个绘制组件成为一个整体,需要创建Shape作为其父组件。

我们要绘制的Logo的大小630px * 630px。声明式UI范式支持多种长度单位的设置,在前面的章节中,我们直接使用number作为参数,即采用了默认长度单位vp,虚拟像素单位。vp和设备分辨率以及屏幕密度有关。比如设备分辨率为1176 * 2400,屏幕基准密度(resolution)为3,vp = px / resolution,则该设备屏幕宽度是392vp。

但是绘制组件采用svg标准,默认采取px为单位的,为方便统一,在这绘制Logo这一部分,统一采取px为单位。声明式UI框架同样也支持px单位,入参类型为string,设置宽度为630px,即210vp,设置方式为width('630px')或者width(210)。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. build() {
  5. Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  6. Shape() {
  7. }
  8. .height('630px')
  9. .width('630px')
  10. }
  11. .width('100%')
  12. .height('100%')
  13. }
  14. }

4. 给页面填充渐变色。设置为线性渐变,偏移角度为180deg,三段渐变 #BDE895 -->95DE7F --> #7AB967,其区间分别为[0, 0.1], (0.1, 0.6], (0.6, 1]。

  1. .linearGradient(
  2. {
  3. angle: 180,
  4. colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
  5. })

  1. @Entry
  2. @Component
  3. struct Logo {
  4. build() {
  5. Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  6. Shape() {
  7. }
  8. .height('630px')
  9. .width('630px')
  10. }
  11. .width('100%')
  12. .height('100%')
  13. .linearGradient(
  14. {
  15. angle: 180,
  16. colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
  17. })
  18. }
  19. }

5. 绘制第一条路线Path,设置其绘制命令。

  1. Path()
  2. .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')

Path的绘制命令采用svg标准,上述命令可分解为:

M162 128.7

将笔触移动到(Moveto)坐标点(162, 128.7)。

a222 222 0 0 1 100.8 374.4

画圆弧线(elliptical arc)半径rx,ry为222,x轴旋转角度x-axis-rotation为0,角度大小large-arc-flag为0,即小弧度角,弧线方向(sweep-flag)为1,即逆时针画弧线,小写a为相对位置,即终点坐标为(162 + 100.8 = 262.8, 128.7 + 374.4 = 503.1)。

H198

画水平线(horizontal lineto)到198,即画(262.8, 503.1)到(198, 503.1)的水平线。

a36 36 0 0 3 -36 -36

画圆弧线(elliptical arc),含义同上,结束点为(198 - 36 = 162, 503.1 - 36 = 467.1)。

V128.7

画垂直线(vertical lineto)到128.7,即画(162, 467.1)到(162, 128.7)的垂直线。

z

关闭路径(closepath)。

填充颜色为白色。

.fill(Color.White)
  1. @Entry
  2. @Component
  3. struct Logo {
  4. build() {
  5. Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  6. Shape() {
  7. Path()
  8. .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
  9. .fill(Color.White)
  10. }
  11. .height('630px')
  12. .width('630px')
  13. }
  14. .width('100%')
  15. .height('100%')
  16. .linearGradient(
  17. {
  18. angle: 180,
  19. colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
  20. })
  21. }
  22. }

6. 在Shape组件内绘制第二个Path。第二条Path的背景色为渐变色,但是渐变色的填充是其整体的box,所以需要clip将其裁剪,入参为Shape,即按照Shape的形状进行裁剪。

  1. Path()
  2. .commands('M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z')
  3. .fill('none')
  4. .linearGradient(
  5. {
  6. angle: 30,
  7. colors: [["#C4FFA0", 0], ["#ffffff", 1]]
  8. })
  9. .clip(new Path().commands('M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'))

Path的绘制命令比较长,可以将其作为组件的成员变量,通过this调用。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
  5. build() {
  6. ......
  7. Path()
  8. .commands(this.pathCommands1)
  9. .fill('none')
  10. .linearGradient(
  11. {
  12. angle: 30,
  13. colors: [["#C4FFA0", 0], ["#ffffff", 1]]
  14. })
  15. .clip(new Path().commands(this.pathCommands1))
  16. ......
  17. }
  18. }

7. 在Shape组件内绘制第二个Path。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
  5. private pathCommands2:string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'
  6. build() {
  7. Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  8. Shape() {
  9. Path()
  10. .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
  11. .fill(Color.White)
  12. Path()
  13. .commands(this.pathCommands1)
  14. .fill('none')
  15. .linearGradient(
  16. {
  17. angle: 30,
  18. colors: [["#C4FFA0", 0], ["#ffffff", 1]]
  19. })
  20. .clip(new Path().commands(this.pathCommands1))
  21. Path()
  22. .commands(this.pathCommands2)
  23. .fill('none')
  24. .linearGradient(
  25. {
  26. angle: 50,
  27. colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]
  28. })
  29. .clip(new Path().commands(this.pathCommands2))
  30. }
  31. .height('630px')
  32. .width('630px')
  33. }
  34. .width('100%')
  35. .height('100%')
  36. .linearGradient(
  37. {
  38. angle: 180,
  39. colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
  40. })
  41. }
  42. }

完成应用Logo的绘制。Shape组合了三个Path组件,通过svg命令绘制出一个艺术的叶子,寓意绿色健康饮食方式。

8. 添加应用的标题和slogan。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
  5. private pathCommands2:string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'
  6. build() {
  7. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  8. Shape() {
  9. Path()
  10. .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
  11. .fill(Color.White)
  12. Path()
  13. .commands(this.pathCommands1)
  14. .fill('none')
  15. .linearGradient(
  16. {
  17. angle: 30,
  18. colors: [["#C4FFA0", 0], ["#ffffff", 1]]
  19. })
  20. .clip(new Path().commands(this.pathCommands1))
  21. Path()
  22. .commands(this.pathCommands2)
  23. .fill('none')
  24. .linearGradient(
  25. {
  26. angle: 50,
  27. colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]
  28. })
  29. .clip(new Path().commands(this.pathCommands2))
  30. }
  31. .height('630px')
  32. .width('630px')
  33. Text('Healthy Diet')
  34. .fontSize(26)
  35. .fontColor(Color.White)
  36. .margin({ top:300 })
  37. Text('Healthy life comes from a balanced diet')
  38. .fontSize(17)
  39. .fontColor(Color.White)
  40. .margin({ top:4 })
  41. }
  42. .width('100%')
  43. .height('100%')
  44. .linearGradient(
  45. {
  46. angle: 180,
  47. colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
  48. })
  49. }
  50. }

2 -> 添加动画效果

2.1 -> animateTo实现闪屏动画

声明式UI范式组件动画包括属性动画和animateTo显式动画:

  1. 属性动画:设置组件通用属性变化的动画效果。
  2. 显式动画:可以设置组件从状态A到状态B的变化动画效果,包括样式、位置信息和节点的增加删除等,开发者无需关注变化过程,只需指定起点和终点的状态。animateTo还提供播放状态的回调接口,是对属性动画的增强与封装。

闪屏页面的动画效果是Logo图标的渐出和放大效果的动画,动画结束后跳转到食物分类列表页面。接下来,我们就使用animateTo来实现启动页动画的闪屏效果。

1. 动画效果自动播放。闪屏动画的预期效果是,进入Logo页面后,animateTo动画效果自动开始播放,可以借助于组件显隐事件的回调接口来实现。调用Shape的onAppear方法,设置其显式动画。

  1. Shape() {
  2. ...
  3. }
  4. .onAppear(() => {
  5. animateTo()
  6. })

2. 创建opacity和scale数值的成员变量,用装饰器@State修饰。表示其为有状态的数据,即改变会触发页面的刷新。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. @State private opacityValue: number = 0
  5. @State private scaleValue: number = 0
  6. build() {
  7. Shape() {
  8. ...
  9. }
  10. .scale({ x: this.scaleValue, y: this.scaleValue })
  11. .opacity(this.opacityValue)
  12. .onAppear(() => {
  13. animateTo()
  14. })
  15. }
  16. }

3. 设置animateTo的动画曲线curve。Logo的加速曲线为先慢后快,使用贝塞尔曲线cubicBezier,cubicBezier(0.4, 0, 1, 1)。

需要使用动画能力接口中的插值计算,首先要导入curves模块。

import Curves from '@ohos.curves'

@ohos.curves模块提供了线性Curve. Linear、阶梯step、三阶贝塞尔(cubicBezier)和弹簧(spring)插值曲线的初始化函数,可以根据入参创建一个插值曲线对象。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. @State private opacityValue: number = 0
  5. @State private scaleValue: number = 0
  6. private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)
  7. build() {
  8. Shape() {
  9. ...
  10. }
  11. .scale({ x: this.scaleValue, y: this.scaleValue })
  12. .opacity(this.opacityValue)
  13. .onAppear(() => {
  14. animateTo({
  15. curve: this.curve1
  16. })
  17. })
  18. }
  19. }

4. 设置动画时长为1s,延时0.1s开始播放,设置显示动效event的闭包函数,即起点状态到终点状态为透明度opacityValue和大小scaleValue从0到1,实现Logo的渐出和放大效果。

  1. @Entry
  2. @Component
  3. struct Logo {
  4. @State private opacityValue: number = 0
  5. @State private scaleValue: number = 0
  6. private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)
  7. build() {
  8. Shape() {
  9. ...
  10. }
  11. .scale({ x: this.scaleValue, y: this.scaleValue })
  12. .opacity(this.opacityValue)
  13. .onAppear(() => {
  14. animateTo({
  15. duration: 1000,
  16. curve: this.curve1,
  17. delay: 100,
  18. }, () => {
  19. this.opacityValue = 1
  20. this.scaleValue = 1
  21. })
  22. })
  23. }
  24. }

5. 闪屏动画播放结束后定格1s,进入FoodCategoryList页面。设置animateTo的onFinish回调接口,调用定时器Timer的setTimeout接口延时1s后,调用router.replace,显示FoodCategoryList页面。

  1. import router from '@ohos.router'
  2. @Entry
  3. @Component
  4. struct Logo {
  5. @State private opacityValue: number = 0
  6. @State private scaleValue: number = 0
  7. private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)
  8. build() {
  9. Shape() {
  10. ...
  11. }
  12. .scale({ x: this.scaleValue, y: this.scaleValue })
  13. .opacity(this.opacityValue)
  14. .onAppear(() => {
  15. animateTo({
  16. duration: 1000,
  17. curve: this.curve1,
  18. delay: 100,
  19. onFinish: () => {
  20. setTimeout(() => {
  21. router.replace({ url: "pages/FoodCategoryList" })
  22. }, 1000);
  23. }
  24. }, () => {
  25. this.opacityValue = 1
  26. this.scaleValue = 1
  27. })
  28. })
  29. }
  30. }

整体代码如下。

  1. import Curves from '@ohos.curves'
  2. import router from '@ohos.router'
  3. @Entry
  4. @Component
  5. struct Logo {
  6. @State private opacityValue: number = 0
  7. @State private scaleValue: number = 0
  8. private curve1 = Curves.cubicBezier(0.4, 0, 1, 1)
  9. private pathCommands1: string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
  10. private pathCommands2: string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'
  11. build() {
  12. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  13. Shape() {
  14. Path()
  15. .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
  16. .fill(Color.White)
  17. Path()
  18. .commands(this.pathCommands1)
  19. .fill('none')
  20. .linearGradient(
  21. {
  22. angle: 30,
  23. colors: [["#C4FFA0", 0], ["#ffffff", 1]]
  24. })
  25. .clip(new Path().commands(this.pathCommands1))
  26. Path()
  27. .commands(this.pathCommands2)
  28. .fill('none')
  29. .linearGradient(
  30. {
  31. angle: 50,
  32. colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]
  33. })
  34. .clip(new Path().commands(this.pathCommands2))
  35. }
  36. .height('630px')
  37. .width('630px')
  38. .scale({ x: this.scaleValue, y: this.scaleValue })
  39. .opacity(this.opacityValue)
  40. .onAppear(() => {
  41. animateTo({
  42. duration: 1000,
  43. curve: this.curve1,
  44. delay: 100,
  45. onFinish: () => {
  46. setTimeout(() => {
  47. router.replace({ url: "pages/FoodCategoryList" })
  48. }, 1000);
  49. }
  50. }, () => {
  51. this.opacityValue = 1
  52. this.scaleValue = 1
  53. })
  54. })
  55. Text('Healthy Diet')
  56. .fontSize(26)
  57. .fontColor(Color.White)
  58. .margin({ top: 300 })
  59. Text('Healthy life comes from a balanced diet')
  60. .fontSize(17)
  61. .fontColor(Color.White)
  62. .margin({ top: 4 })
  63. }
  64. .width('100%')
  65. .height('100%')
  66. .linearGradient(
  67. {
  68. angle: 180,
  69. colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
  70. })
  71. }
  72. }

2.2 -> 页面转场动画

食物分类列表页和食物详情页之间的共享元素转场,即点击FoodListItem/FoodGridItem后,食物缩略图会放大,随着页面跳转,到食物详情页的大图。

1. 设置FoodListItem和FoodGridItem的Image组件的共享元素转场方法(sharedTransition)。转场id为foodItem.id,转场动画时长为1s,延时0.1s播放,变化曲线为贝塞尔曲线Curves.cubicBezier(0.2, 0.2, 0.1, 1.0) ,需引入curves模块。

共享转场时会携带当前元素的被设置的属性,所以创建Row组件,使其作为Image的父组件,设置背景颜色在Row上。

在FoodListItem的Image组件上设置autoResize为false,因为image组件默认会根据最终展示的区域,去调整图源的大小,以优化图片渲染性能。在转场动画中,图片在放大的过程中会被重新加载,所以为了转场动画的流畅,autoResize设置为false。

  1. // FoodList.ets
  2. import Curves from '@ohos.curves'
  3. @Component
  4. struct FoodListItem {
  5. private foodItem: FoodData
  6. build() {
  7. Navigator({ target: 'pages/FoodDetail' }) {
  8. Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
  9. Row() {
  10. Image(this.foodItem.image)
  11. .objectFit(ImageFit.Contain)
  12. .autoResize(false)
  13. .height(40)
  14. .width(40)
  15. .sharedTransition(this.foodItem.id, { duration: 1000, curve: Curves.cubicBezier(0.2, 0.2, 0.1, 1.0), delay: 100 })
  16. }
  17. .margin({ right: 16 })
  18. Text(this.foodItem.name)
  19. .fontSize(14)
  20. .flexGrow(1)
  21. Text(this.foodItem.calories + ' kcal')
  22. .fontSize(14)
  23. }
  24. .height(64)
  25. }
  26. .params({ foodData: this.foodItem })
  27. .margin({ right: 24, left:32 })
  28. }
  29. }
  30. @Component
  31. struct FoodGridItem {
  32. private foodItem: FoodData
  33. build() {
  34. Column() {
  35. Row() {
  36. Image(this.foodItem.image)
  37. .objectFit(ImageFit.Contain)
  38. .autoResize(false)
  39. .height(152)
  40. .width('100%')
  41. .sharedTransition(this.foodItem.id, { duration: 1000, curve: Curves.cubicBezier(0.2, 0.2, 0.1, 1.0), delay: 100 })
  42. }
  43. Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
  44. Text(this.foodItem.name)
  45. .fontSize(14)
  46. .flexGrow(1)
  47. .padding({ left: 8 })
  48. Text(this.foodItem.calories + 'kcal')
  49. .fontSize(14)
  50. .margin({ right: 6 })
  51. }
  52. .height(32)
  53. .width('100%')
  54. .backgroundColor('#FFe5e5e5')
  55. }
  56. .height(184)
  57. .width('100%')
  58. .onClick(() => {
  59. router.push({ url: 'pages/FoodDetail', params: { foodId: this.foodItem } })
  60. })
  61. }
  62. }

2. 设置FoodDetail页面的FoodImageDisplay的Image组件的共享元素转场方法(sharedTransition)。设置方法同上。

  1. import Curves from '@ohos.curves'
  2. @Component
  3. struct FoodImageDisplay {
  4. private foodItem: FoodData
  5. build() {
  6. Stack({ alignContent: Alignment.BottomStart }) {
  7. Image(this.foodItem.image)
  8. .objectFit(ImageFit.Contain)
  9. .sharedTransition(this.foodItem.id, { duration: 1000, curve: Curves.cubicBezier(0.2, 0.2, 0.1, 1.0), delay: 100 })
  10. Text(this.foodItem.name)
  11. .fontSize(26)
  12. .fontWeight(500)
  13. .margin({ left: 26, bottom: 17.4 })
  14. }
  15. .height(357)
  16. }
  17. }

3 -> 常见组件说明

组件是构建页面的核心,每个组件通过对数据和方法的简单封装,实现独立的可视、可交互功能单元。组件之间相互独立,随取随用,也可以在需求相同的地方重复使用。

声明式开发范式目前可供选择的组件如下表所示。

组件类型
基础组件Blank、Button、Checkbox、CheckboxGroup、DataPanel、DatePicker、Divider、Gauge、Image、ImageAnimator、LoadingProgress、Marquee、Navigation、Progress、QRCode、Radio、Rating、RichText、ScrollBar、Search、Select、Slider、Span、Stepper、StepperItem、Text、TextArea、TextClock、TextInput、TextPicker、TextTimer、TimePicker、Toggle、Web、XComponent
容器组件AlphabetIndexer、Badge、Column、ColumnSplit、Counter、Flex、GridContainer、Grid、GridItem、List、ListItem、Navigator、Panel、Refresh、Row、RowSplit、Scroll、SideBarContainer、Stack、Swiper、Tabs、TabContent
媒体组件Video
绘制组件Circle、Ellipse、Line、Polyline、Polygon、Path、Rect、Shape
画布组件Canvas

感谢各位大佬支持!!!

互三啦!!!

学习交流|商务合作|请联系我
微信名片
注:本文转载自blog.csdn.net的枫叶丹4的文章"https://blog.csdn.net/weixin_74809706/article/details/145183972"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

126
软件工程
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top