# 组件在扩展到安全区域后渲染异常如何解决

#### 问题现象

当动态计算子组件高度并扩展其安全区域后，父容器布局约束失效，导致子组件渲染异常。

问题截图如下：

代码如下：

```
import { display } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  build() {
    Column() {
      Column() {
        Text()
          .width('100%')
          .height(this.getUIContext().px2vp(display.getDefaultDisplaySync().width) / (360 / 640))
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
          .backgroundColor('#E5E5EA');
      }
      .backgroundColor('#666666');

      Text('上部组件间异常空缺，显示父组件深灰色');
    }
    .width('100%')
    .height('100%');
  }
}
```

#### 背景知识

*   expandSafeArea控制组件扩展其安全区域，实现屏幕整体一致，达成沉浸式体验。
*   height设置组件自身的高度，缺省时使用元素自身内容需要的高度。若子组件的高度大于父组件的高度，则会超出父组件的范围。入参为Length，支持确切数值和百分比形式。
*   display.getDefaultDisplaySync()：获取当前默认的display对象。

#### 问题定位

根据组件高度变化可知，组件使用expandSafeArea后仍保持设置的固定高度大小。原因是expandSafeArea会先扩展组件到指定安全区域。此时因为组件固定高度，组件就会表现为原大小上移至安全区域。但是，expandSafeArea是仅影响组件本身的属性（减少组件对组件树的影响，降低重绘压力），对于父组件而言组件的占用位置不变，所以父组件会有一部分空间剩余出来。

#### 分析结论

组件使用expandSafeArea后不建议固定高度。可以使用百分比高度组件，在扩展到安全区域后，调整高度阶段会保持非安全区域占用父组件非安全区域的百分比。

#### 修改建议

aboutToAppear提前计算百分比，组件使用百分比作为高度属性入参。

代码如下：

```
import { display } from '@kit.ArkUI';

@Entry
@Component
struct ExpansionException {
  @State heightNum: number = 0;

  aboutToAppear(): void {
    // 根据高宽比计算高度
    this.heightNum = display.getDefaultDisplaySync().width / (360 / 640) / display.getDefaultDisplaySync().height * 100;
  }

  build() {
    Column() {
      Column() {
        Text()
          .width('100%')
          .height(this.heightNum.toString() + '%')
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
          .backgroundColor('#E5E5EA');
      }
      .backgroundColor('#666666');

      Text('上部组件间异常空缺，显示父组件深灰色');
    }
    .width('100%')
    .height('100%');
  }
}
```

#### 常见FAQ

Q：设置了expandSafeArea属性不生效？

A：使用expandSafeArea属性常会触发以下限制，导致组件并没有扩展安全区域。

*   设置expandSafeArea属性进行组件绘制扩展时，组件不能设置固定宽高尺寸。可尝试用百分比或padding改变组件宽高。
*   设置expandSafeArea属性的组件需与安全区域边界重合。
*   当设置expandSafeArea属性的组件的父组件是滚动类容器，需设置父组件的clip属性，不裁剪内部组件。参考顶部或底部背景延伸案例。

Q：左右两个Column分别设置高度为'calc(100%)'和'100%'。其中设置了'calc(100%)'的Column通过expandSafeArea扩展至状态栏后维持了原有的高度，仅仅只是实现了向上平移的效果，设置了'100%'的Column通过expandSafeArea扩展至状态栏后则是在原有高度的基础上向上延伸。这是为什么？

A：设置expandSafeArea属性进行组件绘制扩展时，建议组件尺寸不要设置固定宽高（百分比除外），当设置固定宽高（包括设置"auto"）时，扩展安全区域的方向只支持\[SafeAreaEdge.TOP, SafeAreaEdge.START\]，扩展后的组件尺寸保持不变。而calc计算得到的高度会被视作一个固定值，因此扩展后保持原有尺寸不变。