img

目录

  • 案例介绍
  • 代码实现
  • 代码详解
  • 数据结构设计
  • 动态内容卡片实现
  • 图片布局优化
  • 总结

案例介绍

动态内容布局是社交媒体应用中的重要功能,需要处理不同长度的文本和图片内容。本案例将展示如何使用Flow和FlowItem组件创建基础的动态内容布局。

代码实现

@Entry
@Component
struct SocialFeedPage {
  @State screenWidth: number = 0
  
  // 动态内容数据
  private posts: Array<{
    id: number,
    user: {
      id: number,
      name: string,
      avatar: string
    },
    content: string,
    images: string[],
    time: string,
    likes: number,
    comments: number,
    shares: number
  }> = [
    {
      id: 1,
      user: { id: 101, name: '用户A', avatar: '/assets/avatar1.jpg' },
      content: '今天天气真好,出去走走拍了几张照片,分享给大家!',
      images: ['/assets/post1_1.jpg', '/assets/post1_2.jpg', '/assets/post1_3.jpg'],
      time: '10分钟前',
      likes: 25,
      comments: 5,
      shares: 3
    }
  ]

  build() {
    Column() {
      // 顶部标题栏
      Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
        Text('社交动态')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
        
        Image('/assets/refresh.png')
          .width(24)
          .height(24)
      }
      .width('100%')
      .height(50)
      .padding({ left: 15, right: 15 })
      .backgroundColor(Color.White)
      
      // 动态内容列表
      Scroll() {
        Column() {
          ForEach(this.posts, (post) => {
            Column() {
              // 用户信息和发布时间
              Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
                Flex({ alignItems: ItemAlign.Center }) {
                  Image(post.user.avatar)
                    .width(40)
                    .height(40)
                    .borderRadius(20)
                    .margin({ right: 10 })
                  
                  Text(post.user.name)
                    .fontSize(16)
                    .fontWeight(FontWeight.Medium)
                }
                
                Text(post.time)
                  .fontSize(14)
                  .fontColor('#999999')
              }
              .width('100%')
              .margin({ bottom: 10 })
              
              // 文本内容
              if (post.content) {
                Text(post.content)
                  .fontSize(16)
                  .margin({ bottom: post.images.length > 0 ? 10 : 0 })
              }
              
              // 图片内容
              if (post.images.length > 0) {
                Flow() {
                  ForEach(post.images, (image: string) => {
                    FlowItem() {
                      Image(image)
                        .width(this.getImageWidth(post.images.length))
                        .height(this.getImageWidth(post.images.length))
                        .objectFit(ImageFit.Cover)
                        .borderRadius(8)
                    }
                    .margin(2)
                  })
                }
                .width('100%')
                .margin({ bottom: 10 })
              }
              
              // 互动按钮
              Flex({ justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
                Row() {
                  Image('/assets/like.png')
                    .width(20)
                    .height(20)
                    .margin({ right: 5 })
                  
                  Text(`${post.likes}`)
                    .fontSize(14)
                    .fontColor('#666666')
                }
                
                Row() {
                  Image('/assets/comment.png')
                    .width(20)
                    .height(20)
                    .margin({ right: 5 })
                  
                  Text(`${post.comments}`)
                    .fontSize(14)
                    .fontColor('#666666')
                }
                
                Row() {
                  Image('/assets/share.png')
                    .width(20)
                    .height(20)
                    .margin({ right: 5 })
                  
                  Text(`${post.shares}`)
                    .fontSize(14)
                    .fontColor('#666666')
                }
              }
              .width('100%')
            }
            .width('100%')
            .padding(15)
            .backgroundColor(Color.White)
            .borderRadius(8)
            .margin({ bottom: 10 })
          })
        }
        .width('100%')
      }
      .width('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
  
  // 计算图片宽度
  private getImageWidth(imageCount: number): number {
    const margin = 4
    let columns = 1
    
    if (imageCount === 1) {
      return this.screenWidth - 30 // 单张图片占满宽度(减去左右边距)
    } else if (imageCount === 2 || imageCount === 4) {
      columns = 2 // 2张或4张图片,每行2列
    } else {
      columns = 3 // 3张或更多图片,每行3列
    }
    
    return (this.screenWidth - 30 - (columns - 1) * margin) / columns
  }
}

代码详解

数据结构设计

  1. 动态内容数据结构:
    private posts: Array<{
      id: number,
      user: {
        id: number,
        name: string,
        avatar: string
      },
      content: string,
      images: string[],
      time: string,
      likes: number,
      comments: number,
      shares: number
    }>
    
    • 包含用户信息、文本内容、图片数组等
    • 记录点赞、评论、分享数量

动态内容卡片实现

  1. 用户信息区域:

    Flex({ justifyContent: FlexAlign.SpaceBetween }) {
      Flex({ alignItems: ItemAlign.Center }) {
        Image(post.user.avatar)
        Text(post.user.name)
      }
      Text(post.time)
    }
    
    • 左侧显示头像和用户名
    • 右侧显示发布时间
  2. 图片布局实现:

    Flow() {
      ForEach(post.images, (image: string) => {
        FlowItem() {
          Image(image)
            .width(this.getImageWidth(post.images.length))
            .height(this.getImageWidth(post.images.length))
            .objectFit(ImageFit.Cover)
            .borderRadius(8)
        }
        .margin(2)
      })
    }
    
    • 使用Flow组件实现图片网格
    • 根据图片数量调整布局

图片布局优化

  1. 图片宽度计算:
    private getImageWidth(imageCount: number): number {
      if (imageCount === 1) {
        return this.screenWidth - 30
      } else if (imageCount === 2 || imageCount === 4) {
        columns = 2
      } else {
        columns = 3
      }
      return (this.screenWidth - 30 - (columns - 1) * margin) / columns
    }
    
    • 单张图片占满宽度
    • 2或4张图片使用2列布局
    • 3张或更多图片使用3列布局

总结

本案例展示了如何使用Flow和FlowItem组件实现动态内容的基础布局。通过合理的数据结构设计和布局优化,实现了文本和图片内容的灵活展示。Flow组件的流式布局特性很好地解决了多图布局的问题,提供了良好的视觉效果。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐