08-自然壁纸实战教程-视频列表-云

发布于:2025-07-11 ⋅ 阅读:(21) ⋅ 点赞:(0)

08-自然壁纸实战教程-视频列表

前言

视频列表页面本质上也是一个数据展示的列表,不同之处在于之前是是展示壁纸,Image组件负责渲染,这里展示的是视频,使用Video组件,另外视频页面也实现了下载的基本功能,由于视频往往比图片要大,所以这里的下载是比较耗时的,因此使用了多线程技术taskpool实现了视频的下载,并且保存到相册。

image-20250701081028571

视频搜索

image-20250701081116823

这个模块其实是老模块了,这里直接提供代码

  // 顶部搜索栏
  Row() {
    TextInput({ placeholder: '搜索视频...', text: $$this.videoViewModel.searchText })
      .width('80%')
      .height(40)
      .backgroundColor('#F5F5F5')
      .borderRadius(20)
      .padding({ left: 15, right: 15 })
      .onChange((text) => {
        this.videoViewModel.params.q = text
      })
      .onSubmit(async () => {
        await this.videoViewModel.search()
      })
    Button('搜索')
      .width('18%')
      .height(40)
      .margin({ left: 8 })
      .borderRadius(20)
      .backgroundColor('#3366CC')
      .onClick(async () => {
        await this.videoViewModel.search()
      })
  }
  .width('100%')
  .padding(10)
  .margin({ top: 6 })

视频分类

image-20250701081239094

视频分类页面也是一个常规的分类滚动结构,可以出用Scroll组件完成基本结构

  Row() {
    Text('类型:')
      .fontSize(16)
      .fontWeight(FontWeight.Medium)
      .margin({ right: 10 })

    // 使用Scroll实现横向滚动
    Scroll() {
      Row() {
        // 使用categories数据源
        ForEach(LocalData.CategoryData, (item: ICategory) => {
          Button({ type: ButtonType.Capsule }) {
            Text(item.text)
              .fontSize(16)
              .fontColor(this.videoViewModel.selectedCategory === item.value ? '#FFFFFF' : '#333333')
              .padding({ left: 5, right: 5 })
          }
          .backgroundColor(this.videoViewModel.selectedCategory === item.value ? '#3366CC' : '#F0F0F0')
          .margin({ right: 12 })
          .height(40)
          .width('auto')
          .padding({ left: 15, right: 15 })
          .onClick(() => {
            this.videoViewModel.selectCategory(item.value)
          })
        })
      }
      .width('auto')
    }
    .scrollable(ScrollDirection.Horizontal)
    .scrollBar(BarState.Off)
    .width('80%')
    .layoutWeight(1)
  }
  .width('100%')
  .padding({ left: 10, right: 10, bottom: 10 })
  .alignItems(VerticalAlign.Center)

LocalData.CategoryData 数据源

  static readonly CategoryData: ICategory[] = [
    {
      "id": 0,
      "text": "背景",
      "value": "backgrounds",
      "icon": "🌅"
    },
    {
      "id": 1,
      "text": "时尚",
      "value": "fashion",
      "icon": "👔"
    },
    {
      "id": 2,
      "text": "自然",
      "value": "nature",
      "icon": "🌲"
    },
    {
      "id": 3,
      "text": "科学",
      "value": "science",
      "icon": "🔬"
    },
    {
      "id": 4,
      "text": "教育",
      "value": "education",
      "icon": "📚"
    },
    {
      "id": 5,
      "text": "感情",
      "value": "feelings",
      "icon": "❤️"
    },
    {
      "id": 6,
      "text": "健康",
      "value": "health",
      "icon": "🏥"
    },
    {
      "id": 7,
      "text": "人",
      "value": "people",
      "icon": "👥"
    },
    {
      "id": 8,
      "text": "宗教",
      "value": "religion",
      "icon": "🙏"
    },
    {
      "id": 9,
      "text": "地方",
      "value": "places",
      "icon": "🌆"
    },
    {
      "id": 10,
      "text": "动物",
      "value": "animals",
      "icon": "🐱"
    },
    {
      "id": 11,
      "text": "工业",
      "value": "industry",
      "icon": "🏭"
    },
    {
      "id": 12,
      "text": "计算机",
      "value": "computer",
      "icon": "💻"
    },
    {
      "id": 13,
      "text": "食品",
      "value": "food",
      "icon": "🍜"
    },
    {
      "id": 14,
      "text": "体育",
      "value": "sports",
      "icon": "🏃"
    },
    {
      "id": 15,
      "text": "交通",
      "value": "transportation",
      "icon": "🚗"
    },
    {
      "id": 16,
      "text": "旅行",
      "value": "travel",
      "icon": "✈️"
    },
    {
      "id": 17,
      "text": "建筑物",
      "value": "buildings",
      "icon": "🏢"
    },
    {
      "id": 18,
      "text": "商业",
      "value": "business",
      "icon": "💼"
    },
    {
      "id": 19,
      "text": "音乐",
      "value": "music",
      "icon": "🎵"
    }
  ]

视频列表

image-20250701081326639

这里是视频列表,我们发送请求获取到视频数据后,使用 LazyForEach 结合 List 实现的视频列表渲染

      // 视频列表
      if (this.videoViewModel.videoList.totalCount() > 0) {
        List() {
          LazyForEach(this.videoViewModel.videoList, (video: VideoData, index: number) => {
            ListItem() {
              Column() {
                // 视频缩略图
                Stack() {
                  Image(video.videos?.medium?.thumbnail || '')
                    .width('100%')
                    .height(200)
                    .borderRadius(8)
                    .objectFit(ImageFit.Cover)

                  // 播放时长
                  if (video.duration) {
                    Text(CommonUtils.formatDuration(video.duration))
                      .fontSize(12)
                      .fontColor($r('sys.color.comp_background_list_card'))
                      .backgroundColor('rgba(0, 0, 0, 0.6)')
                      .borderRadius(4)
                      .padding({
                        left: 6,
                        right: 6,
                        top: 2,
                        bottom: 2
                      })
                  }
                }
                .width('100%')
                .alignContent(Alignment.BottomEnd)

                // 视频信息
                Row() {
                  Column() {
                    Text(video.tags.split(',')[0] || '未知标题')
                      .fontSize(16)
                      .fontWeight(FontWeight.Bold)
                      .margin({ top: 8, bottom: 4 })
                      .maxLines(1)
                      .textOverflow({ overflow: TextOverflow.Ellipsis })

                    Row() {
                      Text(`${video.views || 0} 次观看`)
                        .fontSize(12)
                        .fontColor('#666666')

                      Text(`${video.likes || 0}`)
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ left: 10 })
                    }
                  }
                  .alignItems(HorizontalAlign.Start)
                  .layoutWeight(1)
                }
                .width('100%')
                .padding({
                  left: 4,
                  right: 4,
                  top: 4,
                  bottom: 8
                })
              }
              .width('100%')
              .borderRadius(8)
              .backgroundColor($r('sys.color.comp_background_list_card'))
              .margin({ bottom: 12 })
            }
            .onAppear(() => {
              if (index == (this.videoViewModel.videoList.totalCount() - 5)) {
                this.videoViewModel.loadMore()
              }
            })
            .onClick(() => {
              NavigationUtils.getInstance().navigatePush(NavigationConst.Video_Player_View, video)
            })
          }, (video: VideoData, index: number) => video.id.toString())
        }
        .width('100%')
        .layoutWeight(1)
        .padding({ left: 10, right: 10 })
        .cachedCount(10)
      }

视频详情

视频详情是通过点击视频卡片,然后通过Navigation跳转实现的

 NavigationUtils.getInstance().navigatePush(NavigationConst.Video_Player_View, video)

关于我们

关于青蓝逐码组织


网站公告

今日签到

点亮在社区的每一天
去签到