HarmonyOS 鸿蒙Next实现折叠工具栏效果

HarmonyOS 鸿蒙Next实现折叠工具栏效果

CollapsingToolbar

![CollapsingToolbar animation]

ohpm install @jackiehou/collapsing-toolbar
import { CollapsingToolbar, CollapsingToolbarState } from '@jackiehou/collapsing-toolbar'

@State collapsingState: CollapsingToolbarState = new CollapsingToolbarState()

build() {
  Column() {
    CollapsingToolbar({
        collapseLength:this.param.collapseHeight,//收起来的高度,可以为0
        expandLength:this.param.expandHeight,//展开的高度,必须大于0
        state:this.collapsingState,//折叠的状态
        header: this.header,//顶部可折叠的内容
        content: this.content,//您的内容,如list等
      })
  }.height('100%')
  .width('100%')
}

@LocalBuilder //组件内部@Builder 建议使用@LocalBuilder,不然会碰到this指向的问题
header() {
   //...
}

@LocalBuilder 
content() {
  //...
}
import {
  CollapsingToolbar,
  CollapsingToolbarState,
  lerp,
  lerpColor, lerpPercentage } from '@jackiehou/collapsing-toolbar'

@LocalBuilder
header() { //header的父组件是Stack,其alignContent属性为TopStart
  //header背景色
  Rect({ width: '100%', height: '100%' })
    .fill(this.expandBgColor)
    .opacity(this.collapsingState.progress) //折叠状态透明,展开状态显示
  //返回按钮
  SymbolGlyph($r('sys.symbol.chevron_left'))
    .renderingStrategy(SymbolRenderingStrategy.SINGLE)
    .fontSize(30)
    .fontWeight(FontWeight.Medium)
    .height(this.collapsingState.collapseHeight > 0 ? this.collapsingState.collapseHeight : 56)
    .align(Alignment.Center)
    .margin({ left: 15, })
    .translate({ y: this.collapsingState.yOffset })//pin效果,组件的y轴位置不随CollapsingToolbar滑动而变化
      /**
       *颜色插值器
       * lerpColor方法第一个参数colorStart:CollapsingToolbar完全折叠状态下的颜色
       * lerpColor方法第一个参数colorEnd:CollapsingToolbar完全展开状态下的颜色
       * lerpColor方法第三个参数this.collapsingState.progress:0到1的小数,0:CollapsingToolbar完全折叠状态,1:CollapsingToolbar完全展开状态
       */
    .fontColor([lerpColor(this.collapseFontColor, this.expandFontColor, this.collapsingState.progress)])
    .onClick(() => {
      router.back()
    })
  //标题
  Text('CollapsingToolbar')
    .height(this.collapsingState.collapseHeight > 0 ? this.collapsingState.collapseHeight : 56)
    .textAlign(TextAlign.Center)
    .margin({
      //collapse状态: 居左40vp,
      //expand状态:   左边距居中
      left: this.collapsingState.lerpX(40, '50%'),
      //collapse状态: top:折叠状态工具栏到顶部的距离,
      //expand状态:   上边距居中
      top: this.collapsingState.lerpY(this.collapsingState.maxOffset, '50%'),
    })
    .translate({
      //collapse状态: 不位移,
      //expand状态:   加上margin的expand状态 整体居中
      x: lerpPercentage('0%', '-50%', this.collapsingState.progress),
      y: lerpPercentage('0%', '-50%', this.collapsingState.progress),
    })
    .fontSize(lerp(16, 22, this.collapsingState.progress))
    .maxLines(1)
    .fontWeight(FontWeight.Medium)
    .fontColor(lerpColor(this.collapseFontColor, this.expandFontColor, this.collapsingState.progress))//fontColor颜色插值器

  SymbolGlyph($r('sys.symbol.heart'))
    .renderingStrategy(SymbolRenderingStrategy.SINGLE)
    .fontSize(25)
    .fontWeight(FontWeight.Medium)
    .height(this.collapsingState.collapseHeight > 0 ? this.collapsingState.collapseHeight : 56)
    .align(Alignment.Center)
    .position({ right: 0, bottom: 0 })//修改当前子组件在Stack的align,等同于BottomEnd
    .margin({ right: 15 })
    .fontColor([lerpColor(this.collapseFontColor, this.expandFontColor, this.collapsingState.progress)])//fontColor颜色插值器
}
List() {
  //...
}
.nestedScroll({
  scrollForward: NestedScrollMode.PARENT_FIRST,
  scrollBackward: NestedScrollMode.SELF_FIRST
})
import { CollapsingToolbarStateV2, CollapsingToolbarV2 } from '@jackiehou/collapsing-toolbar'

//折叠的状态
collapsingState: CollapsingToolbarStateV2 = new CollapsingToolbarStateV2()

CollapsingToolbarV2({
    collapseLength:this.param.collapseHeight,//收起来的高度,可以为0
    expandLength:this.param.expandHeight,//展开的高度,必须大于0
    state:this.collapsingState,//折叠的状态
    header: this.header,//顶部可折叠的内容
    content: this.content,//您的内容,如list等
  })
Refresh({refreshing:$$this.isRefresh}) {
  List({ space: 10 }) {
    //...
  }.width("100%").height("100%")
   .nestedScroll({
    scrollForward: NestedScrollMode.PARENT_FIRST,
    scrollBackward: NestedScrollMode.SELF_FIRST
  })
  .onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
    _: Array<GestureRecognizer>): GestureJudgeResult => {
    console.info('ets onGestureRecognizerJudgeBegin child')
    if (current) {
      let target = current.getEventTargetInfo();
      Logger.debug(`type = ${current.getType()} isBuiltIn = ${current.isBuiltIn()}`)
      if (target && current.isBuiltIn() && current.getType() == GestureControl.GestureType.PAN_GESTURE) {
        let panEvent = event as PanGestureEvent;
        Logger.debug(JSON.stringify(panEvent))
        if(this.collapsingState.progress === ToolBarState.Expanded.valueOf() && panEvent.velocityY > 0){
          return GestureJudgeResult.REJECT;
        }
      }
    }
    return GestureJudgeResult.CONTINUE;
  })
}

Refresh+CollapsingToolbar 示例

![Refresh+CollapsingToolbar animation]

最后完整栗子

[https://gitee.com/jackiehou/collapsing-toolbar]


更多关于HarmonyOS 鸿蒙Next实现折叠工具栏效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

感觉很流畅加油

更多关于HarmonyOS 鸿蒙Next实现折叠工具栏效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS NEXT中实现折叠工具栏效果,可以使用CollapseContainer组件。该组件支持展开/折叠动画效果,适用于工具栏等场景。关键属性包括collapse(控制状态)、duration(动画时长)和curve(动画曲线)。示例代码:

@Entry
@Component
struct ToolbarExample {
  @State isCollapsed: boolean = false

  build() {
    Column() {
      CollapseContainer({ collapse: this.isCollapsed, curve: Curve.Ease }) {
        // 工具栏内容
        Row() {
          Button('功能1')
          Button('功能2')
        }
      }
      .duration(300)

      Button(this.isCollapsed ? '展开' : '折叠')
        .onClick(() => {
          this.isCollapsed = !this.isCollapsed
        })
    }
  }
}

在HarmonyOS Next中实现折叠工具栏效果,使用@jackiehou/collapsing-toolbar组件是一个高效的解决方案。该组件提供了CollapsingToolbar和CollapsingToolbarV2两种实现方式,支持自定义折叠/展开高度、状态管理以及内容插值动画。

关键点:

  1. 安装:通过ohpm安装组件包
  2. 基本使用:需要定义collapseLength(折叠高度)和expandLength(展开高度)
  3. 动画效果:利用lerp、lerpColor等方法实现平滑过渡
  4. 嵌套滚动:必须为List等组件设置nestedScroll属性
  5. 刷新组件:需要处理手势事件传递问题

组件特点:

  • 支持状态管理V2版本
  • 提供丰富的插值方法(lerp, lerpColor等)
  • 支持自定义header和content
  • 完善的嵌套滚动处理

建议参考提供的示例代码快速集成,特别是处理Refresh组件时的特殊注意事项。该组件已实现Material Design风格的折叠效果,可直接用于实际项目开发。

回到顶部