文档管理中心
FAQ应用框架开发UI框架UI界面实现可展开的首页缩略图

实现可展开的首页缩略图

问题现象

如何在新闻等列表页面中实现可展开的缩略图?

背景知识

  • UIContext提供animateTo接口,用于在因闭包代码引起的状态变化时,插入过渡动画,从而实现平滑的界面状态转换效果。
  • Flex是以弹性方式布局子组件的容器组件,能够高效地排列、对齐子元素并分配剩余空间。

解决方案

  1. 创建一个名为scrollItems的自定义组件。在build函数中,先用Text显示标题,再通过Flex布局展示内容。当flag为true时,Flex使用横向排列;当flag为false时,改为纵向排列。
  2. 为Flex添加点击事件onClick,点击时调用animateTo方法触发动画效果,并将flag的值取反,从而实现布局方向的切换动画。
  3. 在父组件中使用ForEach对scrollItems进行循环渲染,传入不同的数据,实现多个模块的复用展示。每个scrollItems都可以独立切换布局。
收起
自动换行
深色代码主题
复制
  1. @Entry
  2. @Component
  3. struct ExpandableThumbnailDemo {
  4. @State arr: string[] = ['国内新闻', '国际新闻', '生活娱乐', '信息世界'];
  5. build() {
  6. Scroll() {
  7. Column() {
  8. ForEach(this.arr, (item: string, index: number) => {
  9. scrollItems({ text: item, colorID: index }).transition({ type: TransitionType.All });
  10. }, (value: string) => value);
  11. };
  12. }
  13. .width('100%')
  14. .height('100%')
  15. .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
  16. .align(Alignment.Top);
  17. }
  18. }
  19. @Component
  20. struct scrollItems {
  21. @State flag: boolean = true;
  22. text: string = '';
  23. colorID: number = 0;
  24. color: string = ((index: number): string => {
  25. const colors: string[] = ['255,0,0', '255,0,0', '255,0,0', '255,0,0'];
  26. return colors[index];
  27. })(this.colorID);
  28. build() {
  29. Column() {
  30. Text(this.text)
  31. .width('100%')
  32. .height(25)
  33. .margin({ bottom: 3 })
  34. .fontColor(this.color);
  35. Flex({
  36. direction: this.flag ? FlexDirection.Row : FlexDirection.Column, // 横向布局和纵向布局切换
  37. justifyContent: FlexAlign.Start,
  38. alignItems: ItemAlign.Start
  39. }) {
  40. Column() {
  41. Image($r('app.media.startIcon')); // 此处仅为样例,请开发者更换为可用图片
  42. }
  43. .width(this.flag ? 80 : '100%')
  44. .height(this.flag ? 80 : 240)
  45. .borderRadius(4)
  46. .backgroundColor('#ffadcfff')
  47. .margin({ right: 7, bottom: 7 });
  48. Column() {
  49. Row() {
  50. Text('国内发生重大新闻');
  51. }
  52. .width('100%')
  53. .height(20)
  54. .backgroundColor('#ffadcfff')
  55. .borderRadius(4)
  56. .padding({ left: 10 });
  57. Row() {
  58. Text('国外发生重大新闻');
  59. }
  60. .width('70%')
  61. .height(20)
  62. .backgroundColor('#FFE8F0FF')
  63. .borderRadius(4)
  64. .padding({ left: 10 })
  65. .margin({ top: 10 });
  66. Row() {
  67. Text('国外发生了重大新闻');
  68. }
  69. .width('75%')
  70. .height(20)
  71. .backgroundColor('#FFE8F0FF')
  72. .padding({ left: 10 })
  73. .borderRadius(4)
  74. .margin({ top: 10 });
  75. if (!this.flag) {
  76. Row() {
  77. Text('国内发生了重大新闻');
  78. }
  79. .width('70%')
  80. .height(20)
  81. .backgroundColor('#FFE8F0FF')
  82. .borderRadius(4)
  83. .padding({ left: 10 })
  84. .margin({ top: 10 });
  85. Row() {
  86. Text('国外发生大新闻');
  87. } // 最小每行内容
  88. .width('75%')
  89. .height(20)
  90. .backgroundColor('#FFE8F0FF')
  91. .padding({ left: 10 })
  92. .borderRadius(4)
  93. .margin({ top: 10 });
  94. Row() {
  95. Text('国内发生大新闻');
  96. } // 最小每行内容
  97. .width('75%')
  98. .height(20)
  99. .backgroundColor('#FFE8F0FF')
  100. .padding({ left: 10 })
  101. .borderRadius(4)
  102. .margin({ top: 10 });
  103. }
  104. }
  105. .alignItems(HorizontalAlign.Start);
  106. }
  107. .width('100%')
  108. .height(this.flag ? 95 : 430)
  109. .padding({
  110. top: 7,
  111. left: 7,
  112. bottom: 7,
  113. right: 7
  114. })
  115. .margin({ bottom: 5 })
  116. .borderRadius(8)
  117. .shadow({ radius: 10, color: 'rgba(0,0,0,1)' })
  118. .onClick(() => {
  119. // 布局切换动画效果
  120. this.getUIContext().animateTo({ duration: 500, curve: Curve.FastOutSlowIn }, () => {
  121. this.flag = !this.flag;
  122. });
  123. });
  124. }
  125. .width('100%')
  126. .padding({ left: 20, right: 20 })
  127. .margin({ top: 20 });
  128. }
  129. }
在 FAQ 中进行搜索
请输入您想要搜索的关键词