HarmonyOS鸿蒙Next中窗口非全屏下如何适配shadow沉浸式

HarmonyOS鸿蒙Next中窗口非全屏下如何适配shadow沉浸式 cke_205.png

当前窗口为非全屏窗口,页面使用Stack组件,在底部使用shadow实现阴影效果,如何将阴影效果扩散到底部导航栏,实现沉浸式效果

对应代码效果

cke_17841.png


更多关于HarmonyOS鸿蒙Next中窗口非全屏下如何适配shadow沉浸式的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

开发者您好,您可以尝试使用组件的expandSafeArea属性,来实现控制组件扩展其安全区域,安全区域是指页面的显示区域,默认情况下开发者开发的界面都布局在安全区域内,不与系统设置的避让区比如状态栏、导航栏区域重叠。通过expandSafeArea属性支持组件不改变布局情况下扩展其绘制区域至安全区外。如果拓展安全区域没有能解决您的问题,麻烦请您提供一下您的完整的代码demo以及测试版本信息(DevEco Studio版本信息和测试手机的版本信息),方便定位您的问题。

更多关于HarmonyOS鸿蒙Next中窗口非全屏下如何适配shadow沉浸式的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


帮你搜索了一下,还没有实测,可以参考一下:

要在非全屏窗口下让底部组件的shadow实现 “沉浸式扩散到底部导航栏”,核心是解决 “阴影被父容器裁剪”+“调整阴影参数与布局层级”,以下是鸿蒙 ArkTS 的具体实现方案:

问题根源

你当前的阴影被 “裁剪”,是因为:

  1. 父容器(如Stack)默认overflow: Hidden,会裁剪组件溢出的阴影;
  2. 非全屏窗口的布局边界限制了阴影的扩散范围;
  3. 阴影的偏移 / 扩散参数未向 “底部导航栏方向” 优化。

解决方案(分步修改代码)

步骤 1:让父容器允许阴影溢出(关键:关闭裁剪)

将包裹底部组件的父容器(如Stack)的overflow设为Visible,允许阴影溢出父容器边界:

Stack({ 
  overflow: Overflow.Visible // 核心:关闭父容器的内容裁剪,让阴影能溢出
}) {
  // 其他页面内容组件(比如选项列表)
  Column({ space: 15 }) {
    // 选项列表(对应截图中的单选框)
    Radio({ value: '1' }).label('关口常开想')
    Radio({ value: '2' }).label('辛辛苦苦')
    // ...其他选项
  }
  .width('100%')
  .padding(15)

  // 底部组件(带阴影)
  this.renderBottomBar()
}
.width('100%')
.height('100%')
// 若页面有安全区域避让,可调整底部padding(避免阴影被安全区域挤压)
.padding({ bottom: 0 }) 

步骤 2:优化底部组件的shadow参数(向导航栏扩散)

调整shadowoffsetY(向下偏移)和spread(阴影扩散范围),让阴影向底部导航栏方向延伸:

// 底部组件渲染函数
renderBottomBar() {
  return Column()
    .width('100%')
    .backgroundColor('#FFFFFF')
    // 优化shadow参数:向下偏移+增加扩散范围
    .shadow({
      radius: vp2px(6), // 阴影模糊半径
      color: 'rgba(0, 0, 0, 0.1012)', // 阴影颜色
      offsetY: vp2px(3), // 阴影向Y轴下方偏移(贴近导航栏)
      spread: vp2px(2) // 增加阴影的扩散范围(让阴影更“宽”)
    })
    .padding({ left: 15, right: 15, top: 8, bottom: 8 })
    .justifyContent(FlexAlign.SpaceBetween)
    .flexDirection(FlexDirection.Row)
    .children([
      Text(`已选择 0 个 ↑`).fontSize(14),
      Row({ space: 10 }).children([
        Button('清空').backgroundColor('#F5F5F5'),
        Button('确定').backgroundColor('#007AFF').fontColor('#FFFFFF')
      ])
    ])
    // 固定到底部(非全屏窗口下更稳定)
    .position({ bottom: 0 })
}

步骤 3:适配非全屏窗口的布局边界

若窗口是非全屏(比如自定义了窗口大小),需确保窗口本身不裁剪内容

  • 若你通过window.setWindowSize设置了非全屏尺寸,可补充设置窗口的clip属性为false(鸿蒙 6 + 支持):
// 在Ability的onWindowStageCreate中设置窗口属性
onWindowStageCreate(windowStage: window.WindowStage) {
  windowStage.getMainWindow().then((mainWindow) => {
    // 设置非全屏尺寸
    mainWindow.setWindowSize({ width: 300, height: 500 });
    // 允许窗口内容溢出(避免阴影被窗口边界裁剪)
    mainWindow.setClip(false); 
  });
}

最终效果说明

  1. 父容器Stackoverflow: Visible会让底部组件的阴影突破容器边界;
  2. shadowoffsetYspread参数让阴影向底部导航栏方向扩散;
  3. 窗口的setClip(false)确保非全屏窗口不会裁剪溢出的阴影。

通过这三步调整,底部组件的阴影就能 “沉浸式扩散到底部导航栏区域”,不会被容器 / 窗口裁剪,同时保持样式自然。

在HarmonyOS Next中,窗口非全屏下适配shadow沉浸式,需使用Window模块的setWindowSystemBarEnable方法,并配合setWindowLayoutFullScreen方法。通过setWindowSystemBarEnable设置导航栏和状态栏透明,再使用setWindowLayoutFullScreen(false)退出全屏,即可在非全屏窗口下实现沉浸式效果。具体实现涉及ohos.window接口。

在HarmonyOS Next中,要实现非全屏窗口下阴影(shadow)向底部导航栏(Navigation Bar)区域的沉浸式扩散,核心思路是将窗口内容区域扩展至导航栏下方,并配合透明或半透明的导航栏样式。这通常需要窗口能力与UI组件的配合设置。

以下是关键步骤和代码示例:

1. 设置窗口属性,允许内容延伸到导航栏区域

EntryAbilityonWindowStageCreate生命周期中,通过Window对象设置窗口的布局模式。

// EntryAbility.ets
import window from '@ohos.window';

onWindowStageCreate(windowStage: window.WindowStage): void {
  // ... 其他代码,例如设置主页面 ...

  // 获取当前窗口对象
  let mainWindow = await windowStage.getMainWindow();
  // 关键:设置窗口布局为全内容布局,允许内容延伸到系统栏(状态栏和导航栏)下方
  await mainWindow.setWindowLayoutFullScreen(true);
  // 设置导航栏为透明(或半透明),使下方阴影可见
  await mainWindow.setWindowSystemBarEnable(['navigation']);
  await mainWindow.setWindowSystemBarProperties({
    navigationBarColor: '#00000000', // 设置为完全透明
    // 或者使用半透明色,例如 '#33000000'
  });
}

2. 在UI页面中使用Stack并正确应用阴影

在你的页面布局中,确保Stack组件占满全窗口,并为其内容(例如上方的卡片)设置阴影。阴影效果会自然地渲染在Stack所占据的整个区域,包括已经延伸到的导航栏位置。

// 你的页面组件 .ets 文件
@Entry
@Component
struct MyPage {
  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      // 1. 你的主内容,例如一个带有阴影的卡片
      Column() {
        // 你的卡片内容...
      }
      .width('90%')
      .height(200)
      .backgroundColor(Color.White)
      .shadow({
        radius: 20, // 阴影模糊半径
        color: Color.Gray, // 阴影颜色
        offsetX: 0,
        offsetY: 10 // 设置Y轴偏移,使阴影向下扩散
      })
      .margin({ top: 50 })

      // 2. 其他UI组件...
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5') // 设置Stack背景色
  }
}

3. 处理安全区域(可选但建议)

由于内容延伸到了系统栏区域,为了避免关键内容(如按钮、文字)被遮挡,可以使用安全区域组件进行避让。但就你的需求而言,阴影部分正是希望扩散到导航栏,因此可能不需要对阴影元素本身做安全区避让,而是对页面上的可交互内容(如返回按钮、标题)进行避让。

Stack({ alignContent: Alignment.TopStart }) {
  // 使用安全区域组件包裹需要避开系统栏的内容
  SafeArea({
    // 指定避开哪些区域,这里top避开状态栏,bottom避开导航栏
    // 注意:对于希望阴影扩散到底部的场景,承载阴影的组件不应被SafeArea包裹
    edges: { top: true, bottom: true }
  }) {
    Column() {
      // 你的页面标题栏、主要操作按钮等需要避开系统栏的内容
      Text('页面标题')
        .fontSize(20)
        .margin({ top: 10 })
    }
    .width('100%')
  }

  // 你的带阴影的卡片组件放在SafeArea之外,使其可以渲染到导航栏区域
  Column() {
    // 卡片内容...
  }
  .shadow({ ... })
  // ... 其他样式
}

实现原理总结

  • setWindowLayoutFullScreen(true): 这是最关键的一步。它将窗口的布局边界扩展到整个屏幕,包括系统栏(状态栏和导航栏)所占用的区域。UI组件可以绘制到这些区域。
  • setWindowSystemBarProperties: 将导航栏颜色设置为透明或半透明,使得绘制在其下方的阴影效果能够透过导航栏显示出来,从而实现视觉上的“沉浸式扩散”。
  • UI组件层级: 使用Stack作为根容器,确保其尺寸为100%,使其能够占据整个扩展后的窗口区域。将带有阴影的组件放置在Stack中,阴影就会在整个Stack的背景上进行渲染。

通过以上组合配置,即可在HarmonyOS Next的非全屏窗口下,实现阴影效果向底部导航栏区域的沉浸式扩散。

回到顶部