HarmonyOS鸿蒙Next中想实现一个slide滑动不超过90的时候回弹到初始位置的效果,代码如下,动画没效果是为什么?请各位老师赐教

HarmonyOS鸿蒙Next中想实现一个slide滑动不超过90的时候回弹到初始位置的效果,代码如下,动画没效果是为什么?请各位老师赐教

Slider({min:this.minValue,
  max:this.maxValue,
  style: SliderStyle.OutSet,
  direction:Axis.Horizontal,
  value:this.currentValue})
  .height('100%')
  .layoutWeight(1)
  .margin({left:-4,right:-4})
  .selectedColor(Color.Transparent)
  .blockSize({width:50,height:50})
  .blockStyle({ type: SliderBlockType.IMAGE, image: $r('app.media.open_lock_icon') })
  .onChange((value: number, mode: SliderChangeMode)=>{
   //滑动结束检查
    if (mode === SliderChangeMode.End){
      if (value <  this.threshold ) {
        // TODO 动画没效果
        // 执行回弹动画
        this.getUIContext().animateTo({
          duration: 200,
          curve: Curve.Linear
        }, () => {
          this.currentValue = this.minValue
        })
      } else {
        this.currentValue = value
      }
    }
  });

更多关于HarmonyOS鸿蒙Next中想实现一个slide滑动不超过90的时候回弹到初始位置的效果,代码如下,动画没效果是为什么?请各位老师赐教的实战教程也可以访问 https://www.itying.com/category-93-b0.html

10 回复

首先,需要弄清楚动画的含义,animateTo只是针对组件的尺寸属性、布局属性、位置属性等,而value属于该组件的值发生变化,所有使用动画没有作用,

解决这个问题,我的思路是“持续间隔修改value的值”达到动画效果,先看效果:

GIF

以下是完整代码:

@Entry
@Component
struct Index {
  slideInterval: number = 1;
  threshold: number = 60;
  @State currentValue: number = 10;
  @State maxValue: number = 100;
  @State minValue: number = 0;

  build() {
    Column() {
      Slider({
        min: this.minValue,
        max: this.maxValue,
        style: SliderStyle.OutSet,
        direction: Axis.Horizontal,
        value: $$this.currentValue
      })
        .blockColor(Color.Green)
        .trackColor(Color.Red)
        .height('100%')
        .layoutWeight(1)
        .margin({ left: -4, right: -4 })
        .selectedColor(Color.Transparent)
        .blockSize({ width: 50, height: 50 })

        .onChange((value: number, mode: SliderChangeMode) => {
          //当前值每100毫秒减去10,所以会出现为小于零额情况,这时将当前值给他
          if (this.currentValue <= 0) {
            this.currentValue = value;
          }
          
          if (mode === SliderChangeMode.End) {
            if (value < this.threshold) {

             const slideInterval = setInterval(() => {
                if (this.currentValue <= 0) {
                  clearInterval(slideInterval)
                  return;
                }
                //一次左滑10步,可以根据情况修改这个值
                this.currentValue -= 10;

              }, 100) // 计时器,100毫秒执行一次,可以根据自己情况修改
            } else {
              this.currentValue = value
            }
          }
        });
    }
  }
}

如果帮你解决了问题,记得点击“采纳意见”&

更多关于HarmonyOS鸿蒙Next中想实现一个slide滑动不超过90的时候回弹到初始位置的效果,代码如下,动画没效果是为什么?请各位老师赐教的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


效果已实现,多谢赐教;

currentValue需使用@State装饰器确保UI响应式更新

尝试将状态更新包裹在animateTo的闭包中,确保动画执行期间状态同步更新

if (mode === SliderChangeMode.End) {
  this.getUIContext().animateTo({
    duration: 200,
    curve: Curve.Linear
  }, () => {
    if (value < this.threshold) {
      this.currentValue = this.minValue; // 在动画闭包内更新状态
    } else {
      this.currentValue = value;
    }
  });
}

按这个优化一下楼主,看看效果:

// 状态声明
@State currentValue: number = this.minValue;
@State threshold: number = 90;

Slider({
  min: this.minValue,
  max: this.maxValue,
  value: this.currentValue, // 绑定响应式变量
  // ...其他参数保持原样
})
.onChange((value: number, mode: SliderChangeMode) => {
  if (mode === SliderChangeMode.End) {
    if (value < this.threshold) {
      animateTo({
        duration: 200,
        curve: Curve.Spring // 弹性曲线增强效果
      }, () => {
        this.currentValue = this.minValue; // 直接修改状态
      });
    } else {
      this.currentValue = value;
    }
  }
})

老师,我是在 @ComponentV2 下进行实现的;

@Local threshold: number = 90; // 90%阈值
@Local minValue: number = 0;
@Local maxValue: number = 100;
@Local currentValue: number = this.minValue;

Slider({
    min: this.minValue,
    max: this.maxValue,
    style: SliderStyle.OutSet,
    direction: Axis.Horizontal,
    value: this.currentValue
})
.height('100%')
.layoutWeight(1)
.margin({ left: -4, right: -4 })
.selectedColor(Color.Transparent)
.blockSize({ width: 50, height: 50 })
.blockStyle({ type: SliderBlockType.IMAGE, image: $r('app.media.open_lock_icon') })
.onChange((value: number, mode: SliderChangeMode) => {
    // 滑动结束检查
    if (mode === SliderChangeMode.End) {
        if (value < this.threshold) {
            // TODO 动画没效果 需要完善
            // 执行回弹动画
            this.getUIContext().animateTo({
                duration: 200,
                curve: Curve.Linear
            }, () => {
                this.currentValue = this.minValue
            })
        } else {
            this.currentValue = this.minValue
            this.showLock = false;
        }
    }
});

没回弹效果,@ComponentV2curve: Curve.Spring 没有这个属性;

谢谢老师回复;

  • 响应式状态是核心@State 装饰的 currentValue 是动画生效的前提,因为 animateTo 需要通过修改状态变量触发 UI 重绘,从而展示动画过程。
  • 延迟执行的作用setTimeout(0) 不会产生实际延迟,但会将动画逻辑放入下一个事件循环,避免与 Slider 自身的 onChange 状态更新冲突。
  • 双向绑定的必要性value: $currentValue 确保 currentValue 的变化能实时反映到 Slider 组件上,动画过程中滑块位置才会平滑移动。

多谢回复,未能解决问题;

  1. @Local currentValue: number = 0; 状态修饰无误;
  2. 增加延时未见效果;

好吧晚上在研究一下,

在HarmonyOS Next中,滑动回弹效果需要正确设置动画参数和滑动事件监听。检查以下几点:

  1. 确保在onTouch事件中正确调用了startAnimation
  2. 确认animationController的duration和curve参数设置正确
  3. 检查translateX属性绑定是否正确
  4. 确保滑动距离计算逻辑准确,当滑动距离<90时执行回弹动画

常见问题可能是动画属性未绑定或滑动距离判断逻辑有误。

在HarmonyOS Next中,你的代码问题可能出在动画执行方式上。以下是几个关键点分析:

  1. 动画上下文问题:getUIContext()可能没有正确获取到动画上下文。建议直接使用组件自身的动画上下文。

  2. 状态更新方式:在ArkUI中,直接赋值可能不会触发UI更新,需要使用状态管理变量。

修改建议(简洁版):

.onChange((value: number, mode: SliderChangeMode) => {
  if (mode === SliderChangeMode.End) {
    if (value < this.threshold) {
      animateTo({ duration: 200 }, () => {
        this.currentValue = this.minValue // 确保currentValue是[@State](/user/State)装饰的
      })
    } else {
      this.currentValue = value
    }
  }
})

主要修改点:

  1. 直接使用animateTo而非通过getUIContext()
  2. 确保currentValue使用@State装饰器声明
  3. 移除不必要的curve参数(Linear是默认值)

这样修改后应该能实现滑动未达阈值时的回弹效果。

回到顶部