HarmonyOS鸿蒙Next中导航栏点击页面切换太生硬,是否有切换动画,有可以提供demo

HarmonyOS鸿蒙Next中导航栏点击页面切换太生硬,是否有切换动画,有可以提供demo 导航栏点击页面切换太生硬,是否有切换动画,可以提供demo嘛

3 回复

可以参考这个文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs 参考demo: 自定义tab页签:

class Tab(tabName: string, tabItem: number, tabIndex: number) {
  Row(space: 20) {
    Text(tabName)
      .fontSize(18)
      .fontColor(tabIndex === this.focusIndex ? Color.Blue : Color.Black)
      .id(tabIndex.toString())
      .onAreaChange((oldValue: Area, newValue: Area) => {
        if (this.focusIndex === tabIndex && (this.indicatorLeftMargin === 0 || this.indicatorWidth === 0)){
          if (newValue.position.x != undefined) {
            let positionX = Number.parseFloat(newValue.position.x.toString())
            this.indicatorLeftMargin = Number.isNaN(positionX) ? 0 : positionX
          }
          let width = Number.parseFloat(newValue.width.toString())
          this.tabWidth = Number.isNaN(width) ? 0 : width
          this.indicatorWidth = this.tabWidth
        }
      })
  }
  .justifyContent(FlexAlign.Center)
  .constraintSize({ minWidth: 35 })
  .width(100)
  .height(30)
  .onClick(() => {
    this.controller.changeIndex(tabIndex)
    this.focusIndex = tabIndex
  })
  .backgroundColor("#ffb7b7b7")
}
Stack(alignContent: Alignment.TopStart) {
  Column() {
    // 页签
    Row(space: 8) {
      List(space: 20, initialIndex: 0, scroller: this.scrollerForScroll) {
        ForEach(this.tabArray, (item: number, index: number) => {
          ListItem() {
            this.Tab("页签 " + item, item, index)
          }
        }, (item: string) => item)
      }
      .listDirection(Axis.Horizontal)
      .height(30)
      .width('80%')
      .friction(0.6)
      .alignListItem(ListItemAlign.Start)
      .scrollBar(BarState.Off)
      .width('80%')
      .backgroundColor("#ffb7b7b7")
      .onScroll((xOffset: number, yOffset: number) => {
        this.indicatorLeftMargin -= xOffset
      })
      this.textTest('更多')

    }
    .alignItems(VerticalAlign.Bottom)
    .width('100%')
    .backgroundColor("#ffb7b7b7")

  }
  .alignItems(HorizontalAlign.Start)
  .width('100%')

  Column()
    .height(2)
    .width(this.indicatorWidth)
    .margin({ left: this.indicatorLeftMargin, top:30})
    .backgroundColor(Color.Blue)
  //当下划线滑到"更多"下时进行遮挡
  Column()
    .height(10)
    .width("20%")
    .margin({ left: '80%', top:28})
    .backgroundColor("#ffb7b7b7")
}
滑动动画

Tabs(barPosition: BarPosition.Start, controller: this.controller) {
  ...
}
.onChange((index: number) => {
  console.log('foo change')
  this.focusIndex = index
  //页签切换时tabbar自动滚动
  this.scrollerForScroll.scrollToIndex(index-1,true)
})
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
  // 切换动画开始时触发该回调。下划线跟着页面一起滑动
  this.focusIndex = targetIndex
  let targetIndexInfo = this.getTextInfo(targetIndex)
  this.startAnimateTo(this.animationDuration, targetIndexInfo.left, targetIndexInfo.width)
})
.onAnimationEnd((index: number,event: TabsAnimationEvent) => {
  // 切换动画结束时触发该回调。下划线动画停止。
  let currentIndicatorInfo = this.getCurrentIndicatorInfo(index,event)
  this.startAnimateTo(0,currentIndicatorInfo.left,currentIndicatorInfo.width)
})
.onGestureSwipe((index: number,event: TabsAnimationEvent) => {
  // 在页面跟手滑动过程中,逐帧触发该回调。
  let currentIndicatorInfo = this.getCurrentIndicatorInfo(index,event)
  this.focusIndex = currentIndicatorInfo.index
  this.indicatorLeftMargin = currentIndicatorInfo.left
  this.tabWidth = currentIndicatorInfo.width
  this.indicatorWidth = currentIndicatorInfo.width
})
根据id获取当前tab的相关信息(宽度/left margin)

private getTextInfo(index: number): Record<string, number> {
  let strJson = getInspectorByKey(index.toString())
  try {
  let obj: Record<string, string> = JSON.parse(strJson)
  let rectInfo: number[][] = JSON.parse('[' + obj.$rect + ']')
  return { 'left': px2vp(rectInfo[0][0]), 'width': px2vp(rectInfo[1][0] - rectInfo[0][0]) }
} catch (error) {
  return { 'left': 0, 'width': 0 }
}
}

更多关于HarmonyOS鸿蒙Next中导航栏点击页面切换太生硬,是否有切换动画,有可以提供demo的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,导航栏点击页面切换的动画效果可以通过PageTransitionPageTransitionEnterPageTransitionExit等接口来实现。以下是一个简单的Demo示例,展示了如何为页面切换添加动画效果:

import { PageTransition, PageTransitionEnter, PageTransitionExit } from '@ohos.arkui.advanced';

@Entry
@Component
struct Index {
  @State currentPage: string = 'Page1';

  build() {
    Column() {
      Button('Switch Page')
        .onClick(() => {
          this.currentPage = this.currentPage === 'Page1' ? 'Page2' : 'Page1';
        });

      PageTransition({ duration: 300 })
        .onEnter((transition: PageTransitionEnter) => {
          transition.opacity(0).translate({ x: 100 }).animate({ duration: 300, curve: 'ease' });
        })
        .onExit((transition: PageTransitionExit) => {
          transition.opacity(1).translate({ x: 0 }).animate({ duration: 300, curve: 'ease' });
        })
        .child(
          this.currentPage === 'Page1' ? Page1() : Page2()
        );
    }
  }
}

@Component
struct Page1 {
  build() {
    Text('Page 1')
      .fontSize(30)
      .margin(20);
  }
}

@Component
struct Page2 {
  build() {
    Text('Page 2')
      .fontSize(30)
      .margin(20);
  }
}

在这个示例中,PageTransition用于定义页面切换的动画效果,onEnteronExit分别定义了页面进入和退出时的动画。通过调整opacitytranslate等属性,可以实现不同的动画效果。

在HarmonyOS鸿蒙Next中,默认的导航栏切换是有动画效果的。如果觉得切换效果生硬,可以通过自定义PageTransition动画来优化。以下是一个简单的Demo示例:

import { PageTransition, PageTransitionOptions } from '@ohos.router';

// 定义页面切换动画
const options: PageTransitionOptions = {
  duration: 300, // 动画持续时间
  curve: 'ease-in-out' // 动画曲线
};

// 应用动画
PageTransition.startAnimation(options)
  .then(() => {
    console.log('Page transition animation started');
  })
  .catch((err) => {
    console.error('Failed to start page transition animation', err);
  });

通过调整durationcurve参数,可以优化页面切换的流畅度。

回到顶部