HarmonyOS鸿蒙Next中怎么实现用v2状态管理,半模态弹窗弹出后非弹窗区域的高斯模糊效果?

HarmonyOS鸿蒙Next中怎么实现用v2状态管理,半模态弹窗弹出后非弹窗区域的高斯模糊效果? 【问题描述】:怎么实现用v2状态管理,半模态弹窗弹出后非弹窗区域的高斯模糊效果?

【问题现象】:我参考了半模态弹窗高度问题-行业常见问题-公共关键技术方案 - 华为HarmonyOS开发者以及如何给视频背景添加高斯模糊-行业常见问题-理财保险类行业实践 - 华为HarmonyOS开发者实现了半模态弹窗弹出后非弹窗区域的高斯模糊效果但是关闭弹窗后这个模糊效果消失会有1秒左右的延迟该怎么解决

【版本信息】:未涉及

【复现代码】:未涉及

【尝试解决方案】:未涉及


更多关于HarmonyOS鸿蒙Next中怎么实现用v2状态管理,半模态弹窗弹出后非弹窗区域的高斯模糊效果?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

尊敬的开发者,您好,您可以参考foregroundBlurStyle实现高斯模糊,参考如下demo并没有复现您的问题。

示例代码如下:

@Entry
@ComponentV2
struct BindSheetSetting {
  @Local isShow: boolean = false;
  // 控制当前挡位
  @Local sheetSize: number = SheetSize.MEDIUM;
  @Local isObscure: boolean = false;

  @Builder
  customBuilder() {
    Column({ space: 20 }) {
      Blank()
        .height(20);
      Button('MEDIUM')
        .onClick(() => {
          // 设置挡位为屏幕高度一半
          this.sheetSize = SheetSize.MEDIUM;
        });
      Button('LARGE')
        .onClick(() => {
          // 设置挡位为几乎屏幕高度
          this.sheetSize = SheetSize.LARGE;
        });
      Button('200')
        .onClick(() => {
          // 设置挡位为固定数值
          this.sheetSize = 200;
        });
    };
  }

  build() {
    Column() {
      Button('bindSheet')
        .bindSheet($$this.isShow, this.customBuilder(), {
          detents: [SheetSize.MEDIUM, SheetSize.LARGE, 200], // 设置挡位列表
          detentSelection: this.sheetSize, // 当前展示的挡位
          onWillDismiss: () => {
            this.isShow = !this.isShow;
            this.isObscure = !this.isObscure;
          }
        })
        .onClick(() => {
          // 点击触发半模态状态变更
          this.isShow = !this.isShow;
          this.isObscure = !this.isObscure;
        });
    }
    .height('100%')
    .width('100%')
    .foregroundBlurStyle(BlurStyle.Thin,
      {
        colorMode: ThemeColorMode.LIGHT, // 内容模糊效果使用的深浅色模式。
        adaptiveColor: AdaptiveColor.DEFAULT, //内容模糊效果使用的取色模式
        scale: this.isObscure ? 0.8 : 0   //  内容模糊效果程度。默认值:1.0
      });
  }
}

如果还是不能解决您的问题,麻烦您提供下能复现问题的最小demo吧。

更多关于HarmonyOS鸿蒙Next中怎么实现用v2状态管理,半模态弹窗弹出后非弹窗区域的高斯模糊效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


@Entry
@Component
struct SemiModalWithBlur {
  // V2状态管理:弹窗是否显示
  @State isShowSheet: boolean = false;
  // V2状态管理:背景模糊强度
  @State backgroundBlur: number = 0;

  // 弹窗的构建器
  @Builder
  buildSheetContent() {
    Column() {
      Text('这里是半模态弹窗的内容')
        .fontSize(20)
        .margin(20)
      Button('关闭弹窗')
        .onClick(() => {
          // 注意:此处不直接修改状态
          // 而是由系统触发 onWillDismiss 来统一处理
          this.isShowSheet = false;
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  build() {
    Stack() {
      // 背景页面(将被模糊)
      Column() {
        Text('主页面内容...')
          .fontSize(24)
          .margin({ top: 100 })

        Button('打开半模态弹窗')
          .onClick(() => {
            this.isShowSheet = true;
            // 弹窗打开时,立即设置模糊,动画由 animateTo 控制
            this.backgroundBlur = 10;
          })

        // ... 你的其他页面内容
      }
      .width('100%')
      .height('100%')
      .blur(this.backgroundBlur) // 绑定模糊状态
    }
    .width('100%')
    .height('100%')
    // 绑定半模态弹窗
    .bindSheet($$this.isShowSheet, this.buildSheetContent(), {
      // 关键:拦截关闭事件
      onWillDismiss: () => {
        // 使用 animateTo 同步模糊消失动画与弹窗关闭动画
        // 注意:这里我们假设弹窗关闭动画默认为 200ms,因此模糊动画也设为 200ms
        animateTo({ duration: 200, curve: Curve.EaseOut }, () => {
          this.backgroundBlur = 0; // 在动画中重置模糊为0
        });
        // 返回 true 表示允许关闭,系统将继续执行关闭动画
        return true;
      }
    })
  }
}
  1. 定义状态变量:使用V2状态管理(如 @State)来同时控制弹窗的显示和背景的模糊强度。
  2. 绑定模糊属性:将背景组件的 .blur() 属性绑定到模糊强度状态变量上。
  3. 配置生命周期与动画:这是最关键的一步。在 bindSheetonWillDismiss 回调中,调用 animateTo(...) 包裹模糊状态变量的重置代码。你需要将动画的持续时间设置为与弹窗关闭动画一致(例如200ms),这样可以确保高斯模糊效果是平滑消失的,而非突兀地跳变或延迟。

cke_778.jpeg

通过 isObscure 变量来判断非弹窗区域是否高斯模糊;在

@Entry
@ComponentV2
struct BindSheetSetting {
    @Local isShow: boolean = false;
    // 控制当前挡位
    @Local sheetSize: number = SheetSize.MEDIUM;
    @Local isObscure: boolean = false;

    @Builder
    customBuilder() {
        Column({ space: 20 }) {
            Blank()
                .height(20);
            Button('MEDIUM')
                .onClick(() => {
                    // 设置挡位为屏幕高度一半
                    this.sheetSize = SheetSize.MEDIUM;
                });
            Button('LARGE')
                .onClick(() => {
                    // 设置挡位为几乎屏幕高度
                    this.sheetSize = SheetSize.LARGE;
                });
            Button('200')
                .onClick(() => {
                    // 设置挡位为固定数值
                    this.sheetSize = 200;
                });
        };
    }

    build() {
        Column() {
            Button("!!!!!!!!!!!!!!!!!!!!!!!!!!!").onClick(()=>{

            })
            Button("2222222222222").onClick(()=>{

            })
            Button('bindSheet')
                .bindSheet($$this.isShow, this.customBuilder(), {
                    detents: [SheetSize.MEDIUM, SheetSize.LARGE, 200], // 设置挡位列表
                    detentSelection: this.sheetSize, // 当前展示的挡位
                    onWillDismiss: () => {
                        this.isShow = !this.isShow;
                        this.isObscure = !this.isObscure;
                    }
                })
                .onClick(() => {
                    // 点击触发半模态状态变更
                    this.isShow = !this.isShow;
                    this.isObscure = !this.isObscure;
                });
        }
        .height('100%')
        .width('100%')
        .foregroundBlurStyle(BlurStyle.Thin,
            {
                colorMode: ThemeColorMode.LIGHT,
                adaptiveColor: AdaptiveColor.DEFAULT,
                scale: this.isObscure ? 0.8 : 0
            }) 
    }
}

在HarmonyOS Next 中,使用ArkTS的v2状态管理(@State/@Prop等),对背景层(如Stack容器)设置 .blur() 实现高斯模糊。半模态弹窗推荐使用 bindSheetCustomDialogController,弹窗显示时动态添加模糊类(如条件渲染 .blur(radius)),并配合状态变量控制。

半模态弹窗自带背景模糊属性 backgroundBlurStyle,无需手动管理状态。只需在 bindSheet 中设置即可实现弹窗弹出时非弹窗区域自动高斯模糊、关闭时无延迟同步消失:

.bindSheet($$this.isShow, this.mySheet(), {
  height: this.sheetHeight,
  backgroundBlurStyle: BlurStyle.Thick // 背景模糊,弹窗动画内外同步
})

若必须手动实现,延迟的原因是关闭弹窗时高斯模糊组件的退出动画时长与弹窗自身动画不同步。可在半模态的 onWillDismissonDisappear 中直接置 false 并禁用模糊消失动画:

// 在点击关闭时立即无动画移除模糊
this.isBlur = false;
animateTo({ duration: 0 }, () => { this.isShow = false; });

但推荐使用系统属性,效果更一致且无延迟。

回到顶部