HarmonyOS 鸿蒙Next Refresh自定义刷新区域显示内容

发布于 1周前 作者 nodeper 来自 鸿蒙OS

HarmonyOS 鸿蒙Next Refresh自定义刷新区域显示内容

Refresh自定义刷新区域显示内容,如果我设置了阻尼效果 .pullDownRatio(this.ratio) 那么自定义显示区域的图片动画就无法展示,如果不设置阻尼那么自定义展示区域的动画可以正常展示;代码如下

/**
 * 下拉刷新文案
 */
const PULL_REFRSH = '下拉刷新'
const RELEASE_REFRSH = '释放刷新'
const PULL_REFRSHING = '刷新中...'
// static readonly PULL_REFRSH_SUCCESS = '刷新成功'
const PULL_REFRSH_SUCCESS = ''

@Entry
@Component
struct MainTab{

  @Builder
  barBars(){
    Text('BAR').margin({top: 20, bottom: 20 }).fontSize(18).fontWeight('bold')
  }
  @Builder
  barContents(){
    Tabs() {
      TabContent(){
        RefreshExample()
      }
    }.layoutWeight(1)
    .width('100%')
    .barHeight(0)
    .barMode(BarMode.Scrollable)
    .barOverlap(false)
    .fadingEdge(false)
  }

  build() {
    Column(){
      TopSvBar({
        bars: this.barBars,
        content: this.barContents
      })
    }.width('100%').height('100%')
  }

}


@Component
struct TopSvBar{
  @BuilderParam bars:()=>$void = this.barContents
  @BuilderParam content:()=>$void = this.barContents

  @Builder
  barContents(){}

  build() {

    Column(){
      Text('标题').margin({top: 20, bottom: 20 }).fontSize(18).fontWeight('bold')

      Column(){
        this.bars()
      }.height(50)

      Column(){
        this.content()
      }.layoutWeight(1)
    }
  }
}


@Component
struct RefreshExample {
  @State isRefreshing: boolean = false
  @State refreshString: string = '下拉刷新'

  @State maxRefreshingHeight: number = 200.0
  @State ratio: number = 1

  @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
  @State angle :number = 0

  @State colors: [ResourceColor | LinearGradient, number][] = [] //组件进度条颜色配置
  //设置进度条颜色
  setColors(percentage: number) {
    this.colors = [['#FF585E70', percentage], ['#ffffff', 1 - percentage]]
  }
  @State @Watch('valueChange') currentValue: number = 0 //当前值
  //计算当前值占总的百分比
  getPercentage(): number {
    return Math.min(this.currentValue / 100, 1)
  }
  //当前值改变监听
  valueChange() {
    this.setColors(this.getPercentage())
  }

  @Builder
  customRefreshComponent()
  {
    Row()
    {
      Gauge({ value: this.currentValue, min: 1, max: 100 })
        .startAngle(0)
        .endAngle(320)
        .colors(this.colors)
        .indicator(null)
        .strokeWidth(3)
        .width(20)
        .height(20)
        .visibility((this.refreshString == PULL_REFRSH
          || this.refreshString == RELEASE_REFRSH )? Visibility.Visible : Visibility.None)
      if (this.refreshString == PULL_REFRSHING) {
        Image($r('app.media.startIcon'))
          .rotate({angle: this.angle })
          .width(20)
          .height(20)
      }
      Text(this.refreshString).fontSize(16).margin({left:20})
    }
    .alignItems(VerticalAlign.Center)
    .width("100%")
    .justifyContent(FlexAlign.Center)
    .constraintSize({ minHeight: 32 })
  }


  build() {
    Column() {
      Refresh({ refreshing: $$this.isRefreshing, builder: this.customRefreshComponent() }) {
        List() {
          ForEach(this.arr, (item: string) => {
            ListItem() {
              Text('' + item)
                .width('70%')
                .height(80)
                .fontSize(16)
                .margin(10)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
            }
          }, (item: string) => item)
        }
        .onScrollIndex((first: number) => {
          console.info(first.toString())
        })
        .width('100%')
        .height('100%')
        .alignListItem(ListItemAlign.Center)
        .scrollBar(BarState.Off)
      }
      .pullDownRatio(this.ratio)
      .backgroundColor(0x89CFF0)
      .pullToRefresh(true)
      .refreshOffset(64)
      .onOffsetChange((offset: number) => {
        this.currentValue = (offset / this.maxRefreshingHeight) * 100
        // 越接近最大距离,下拉跟手系数越小
        this.ratio = 1 - Math.pow((offset / this.maxRefreshingHeight), 3)
      })
      .onStateChange((refreshStatus: RefreshStatus) => {
        if(refreshStatus == 1){
          this.refreshString = PULL_REFRSH
        } else if (refreshStatus == 2){
          this.refreshString = RELEASE_REFRSH
        }else if (refreshStatus == 3){
          this.refreshString = PULL_REFRSHING
          animateTo({curve:Curve.Linear,iterations:-1,duration:1000},()=>{
            this.angle = 360
          })
        }else if (refreshStatus == 4){
          this.refreshString = PULL_REFRSH_SUCCESS
        }
      })
      .onRefreshing(() => {
        setTimeout(() => {
          this.isRefreshing = false
          this.angle = 0
        }, 5000)
        console.log('onRefreshing test')
      })
    }
  }
}

更多关于HarmonyOS 鸿蒙Next Refresh自定义刷新区域显示内容的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

以下demo:

import { ComponentContent } from '@ohos.arkui.node';

const PULL_REFRSH = '下拉刷新'
const RELEASE_REFRSH = '释放刷新'
const PULL_REFRSHING = '刷新中...'
const PULL_REFRSH_SUCCESS = ''

@Component
struct MainTab{
  @Builder
  barBars(){
    Text('BAR').margin({top: 20, bottom: 20 }).fontSize(18).fontWeight('bold')
  }
  @Builder
  barContents(){
    Tabs() {
      TabContent(){
        RefreshExample()
      }
    }.layoutWeight(1)
    .width('100%')
    .barHeight(0)
    .barMode(BarMode.Scrollable)
    .barOverlap(false)
    .fadingEdge(false)
  }

  build() {
    Column(){
      TopSvBar({
        bars: this.barBars,
        content: this.barContents
      })
    }.width('100%').height('100%')
  }
}

@Component
struct TopSvBar{
  @BuilderParam 
  bars:()=>$void = this.barContents
  @BuilderParam 
  content:()=>$void = this.barContents
  @Builder
  barContents(){}

  build() {
    Column(){
      Text('标题').margin({top: 20, bottom: 20 }).fontSize(18).fontWeight('bold')
      Column(){
        this.bars()
      }.height(50)

      Column(){
        this.content()
      }.layoutWeight(1)
    }
  }
}

class Params {
  angle: number = 0

  constructor(angle: number) {
    this.angle = angle;
  }
}

function customRefreshingContent(params: Params) {
  Row () {
    Image($r('app.media.startIcon'))
      .rotate({ angle: params.angle })
      .width(20)
      .height(20)
    Text("刷新中").fontSize(16).margin({ left: 20 })
  }
  .alignItems(VerticalAlign.Center)
  .width("100%")
  .justifyContent(FlexAlign.Center)
  .constraintSize({ minHeight: 32 })
}

@Component
struct RefreshExample {
  @State isRefreshing: boolean = false
  @State refreshString: string = '下拉刷新'

  private contentNode?: ComponentContent<Object> = undefined
  private params: Params = new Params(0)

  @State maxRefreshingHeight: number = 200.0
  @State ratio: number = 1

  @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
  @State angle :number = 0

  @State colors: [ResourceColor | LinearGradient, number][] = [] //组件进度条颜色配置
  setColors(percentage: number) {
    this.colors = [['#FF585E70', percentage], ['#ffffff', 1 - percentage]]
  }
  @State @Watch('valueChange') currentValue: number = 0 //当前值
  getPercentage(): number {
    return Math.min(this.currentValue / 100, 1)
  }
  valueChange() {
    this.setColors(this.getPercentage())
  }

  aboutToAppear(): void {
    let uiContext = this.getUIContext()
    this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent), this.params)
  }

  build() {
    Column () {
      Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode}) {
        List () {
          ForEach(this.arr, (item: string) => {
            ListItem () {
              Text('' + item)
                .width('70%')
                .height(80)
                .fontSize(16)
                .margin(10)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
            }
          }, (item: string) => item)
        }
        .onScrollIndex((first: number) => {
          console.info(first.toString())
        })
        .width('100%')
        .height('100%')
        .alignListItem(ListItemAlign.Center)
        .scrollBar(BarState.Off)
      }
      .pullDownRatio(this.ratio)
      .backgroundColor(0x89CFF0)
      .pullToRefresh(true)
      .refreshOffset(64)
      .onOffsetChange((offset: number) => {
        // 越接近最大距离,下拉跟手系数越小
        this.ratio = 1 - Math.pow((offset / this.maxRefreshingHeight), 3)
      })
      .onStateChange((refreshStatus: RefreshStatus) => {
        if (refreshStatus == 3){
          this.refreshString = PULL_REFRSHING
          animateTo({curve:Curve.Linear,iterations:-1,duration:1000},()=>{
            this.params.angle = 360
            // 更新自定义组件内容
            this.contentNode?.update(this.params)
          })
        }
      })
      .onRefreshing(() => {
        setTimeout(() => {
          this.isRefreshing = false
          this.angle = 0
        }, 5000)
        console.log('onRefreshing test')
      })
    }
  }
}

更多关于HarmonyOS 鸿蒙Next Refresh自定义刷新区域显示内容的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对帖子标题“HarmonyOS 鸿蒙Next Refresh自定义刷新区域显示内容”的问题,以下是专业且简洁的回答:

在HarmonyOS鸿蒙系统中,实现Next Refresh自定义刷新区域显示内容的功能,主要依赖于鸿蒙提供的UI框架和组件。你需要通过自定义组件或修改现有组件的刷新逻辑,来指定哪些区域需要在数据更新时重新渲染。

具体来说,你可以:

  1. 定义自定义组件:创建一个新的自定义组件,并在其中实现数据更新和UI刷新的逻辑。确保在数据变化时,只有指定的区域被重新渲染。

  2. 使用刷新机制:鸿蒙系统可能提供了类似于其他UI框架的刷新机制(如SwiftUI的SwiftUI.Refreshable),你需要找到并应用这些机制到你的自定义组件或页面中。

  3. 优化渲染性能:在自定义刷新区域时,注意优化渲染性能,避免不必要的重绘和重排,以提升用户体验。

  4. 测试与调试:在开发过程中,不断测试自定义刷新区域的行为,确保它在各种情况下都能正确显示内容。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部