img

案例介绍

本教程将介绍如何实现新闻应用动态标签的交互功能。我们将实现标签切换、新闻点击等交互效果,提升用户体验。

代码实现

@Entry
@Component
struct DynamicTabContentExample {
  @State currentIndex: number = 0
  private tabsController: TabsController = new TabsController()
  
  build() {
    Column() {
      Tabs({ controller: this.tabsController, index: this.currentIndex }) {
        ForEach(this.newsCategories, (category, index) => {
          TabContent() {
            List() {
              ForEach(this.newsData[category.id], (news) => {
                ListItem() {
                  if (news.hasImage) {
                    Row({ space: 12 }) {
                      Column({ space: 4 }) {
                        Text(news.title)
                          .fontSize(16)
                          .fontWeight(FontWeight.Medium)
                          .maxLines(2)
                          .textOverflow({ overflow: TextOverflow.Ellipsis })
                        
                        Row({ space: 8 }) {
                          Text(news.source)
                            .fontSize(12)
                            .fontColor('#666666')
                          
                          Text(news.time)
                            .fontSize(12)
                            .fontColor('#666666')
                        }
                      }
                      .layoutWeight(1)
                      .alignItems(HorizontalAlign.Start)
                      
                      Stack() {
                        Text('图')
                          .fontSize(16)
                          .fontColor('#FFFFFF')
                      }
                      .width(80)
                      .height(60)
                      .backgroundColor(category.color)
                      .borderRadius(4)
                    }
                    .width('100%')
                    .padding(16)
                  } else {
                    Column({ space: 4 }) {
                      Text(news.title)
                        .fontSize(16)
                        .fontWeight(FontWeight.Medium)
                        .maxLines(2)
                        .textOverflow({ overflow: TextOverflow.Ellipsis })
                      
                      Row({ space: 8 }) {
                        Text(news.source)
                          .fontSize(12)
                          .fontColor('#666666')
                        
                        Text(news.time)
                          .fontSize(12)
                          .fontColor('#666666')
                      }
                    }
                    .width('100%')
                    .padding(16)
                  }
                }
                .height(news.hasImage ? 92 : 72)
                .onClick(() => {
                  // 处理新闻点击事件
                  this.handleNewsClick(category.id, news)
                })
                .gesture(
                  LongPressGesture()
                    .onAction(() => {
                      // 处理长按事件
                      this.showNewsOptions(category.id, news)
                    })
                )
              })
            }
            .width('100%')
            .height('100%')
            .divider({ strokeWidth: 1, color: '#F1F3F5' })
            .onScrollIndex((firstIndex: number) => {
              // 处理滚动事件
              this.handleListScroll(category.id, firstIndex)
            })
          }
          .tabBar(this.CustomTabBar(category, index))
        })
      }
      .vertical(false)
      .scrollable(true)
      .barMode(BarMode.Scrollable)
      .barWidth('100%')
      .barHeight(48)
      .onChange((index: number) => {
        // 处理标签切换
        this.handleTabChange(index)
      })
    }
  }

  // 处理标签切换
  handleTabChange(index: number) {
    this.currentIndex = index
    // 可以在这里加载更多数据
    const category = this.newsCategories[index]
    this.loadMoreNews(category.id)
  }

  // 处理新闻点击
  handleNewsClick(categoryId: string, news: any) {
    // 这里可以实现新闻详情页跳转
    console.info(`点击了${categoryId}分类的新闻:${news.title}`)
  }

  // 显示新闻操作选项
  showNewsOptions(categoryId: string, news: any) {
    // 这里可以显示分享、收藏等操作菜单
    console.info(`长按了${categoryId}分类的新闻:${news.title}`)
  }

  // 处理列表滚动
  handleListScroll(categoryId: string, firstIndex: number) {
    // 这里可以实现下拉刷新或上拉加载更多
    if (firstIndex > this.newsData[categoryId].length - 5) {
      this.loadMoreNews(categoryId)
    }
  }

  // 加载更多新闻
  loadMoreNews(categoryId: string) {
    // 这里可以实现分页加载
    const moreNews = this.generateMockNewsData(categoryId, 5)
    this.newsData[categoryId].push(...moreNews)
  }
}

代码详解

1. 标签切换处理

.onChange((index: number) => {
  this.handleTabChange(index)
})

handleTabChange(index: number) {
  this.currentIndex = index
  const category = this.newsCategories[index]
  this.loadMoreNews(category.id)
}

切换功能:

  • 更新当前标签索引
  • 触发数据加载
  • 支持动态加载
  • 平滑的切换效果

2. 新闻点击处理

.onClick(() => {
  this.handleNewsClick(category.id, news)
})

handleNewsClick(categoryId: string, news: any) {
  console.info(`点击了${categoryId}分类的新闻:${news.title}`)
}

点击功能:

  • 记录点击事件
  • 支持跳转详情
  • 携带新闻信息
  • 分类信息追踪

3. 长按手势处理

.gesture(
  LongPressGesture()
    .onAction(() => {
      this.showNewsOptions(category.id, news)
    })
)

showNewsOptions(categoryId: string, news: any) {
  console.info(`长按了${categoryId}分类的新闻:${news.title}`)
}

长按功能:

  • 显示操作菜单
  • 支持多种操作
  • 便捷的交互方式
  • 增强用户体验

4. 滚动加载处理

.onScrollIndex((firstIndex: number) => {
  this.handleListScroll(category.id, firstIndex)
})

handleListScroll(categoryId: string, firstIndex: number) {
  if (firstIndex > this.newsData[categoryId].length - 5) {
    this.loadMoreNews(categoryId)
  }
}

滚动功能:

  • 监听滚动位置
  • 触发加载更多
  • 平滑的加载体验
  • 防止频繁加载

总结

本教程展示了如何实现新闻应用动态标签的交互功能。通过实现标签切换、新闻点击、长按操作和滚动加载等功能,我们提升了应用的交互体验。重点关注了交互的流畅性和功能的完整性,为用户提供了便捷的新闻浏览体验。

Logo

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

更多推荐