HarmonyOS鸿蒙Next中为什么用5.0之后顶部和底部有一片空白

HarmonyOS鸿蒙Next中为什么用5.0之后顶部和底部有一片空白 为什么用5.0之后顶部和底部有一片空白

cke_124.png


更多关于HarmonyOS鸿蒙Next中为什么用5.0之后顶部和底部有一片空白的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

典型应用全屏窗口UI元素包括状态栏、应用界面和底部导航条,其中状态栏和导航条,通常在沉浸式布局下称为避让区;避让区之外的区域称为安全区。开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感,从而使用户获得最佳的UI体验。

开发应用沉浸式效果主要要考虑如下两个设计要素:

  • UI元素避让处理:导航条底部区域可以响应点击事件,除此之外的可交互UI元素和应用关键信息不建议放到导航条区域。状态栏显示系统信息,如果与界面元素有冲突,需要考虑避让状态栏。
  • 沉浸式效果处理:将状态栏和导航条颜色与界面元素颜色相匹配,不出现明显的突兀感。

根据设计要素要求,可以通过如下两种方式实现应用沉浸式效果:

  • 调整布局系统为全屏布局,界面元素延伸到状态栏和导航条区域实现沉浸式效果。当不隐藏避让区时,可通过接口查询状态栏和导航条区域进行可交互元素避让处理,并设置状态栏或导航条的颜色等属性与界面元素匹配。当隐藏避让区时,通过对应接口设置全屏布局即可(隐藏避让区场景适用于游戏、电影等应用场景,可以通过从底部上滑唤出导航条)。

    • 全屏显示,不隐藏避让区方案:

      export default class EntryAbility extends UIAbility {
        onWindowStageCreate(windowStage: window.WindowStage): void {
          console.info('Ability onWindowStageCreate');
      
          windowStage.loadContent('pages/Index', (err) => {
            if (err.code) {
              console.error(`Failed to load the content. Code is ${err.code}, message is ${err.message}`);
              return;
            }
      
            let windowClass: window.Window = windowStage.getMainWindowSync();
      
            // 1.设置窗口全屏
            let isLayoutFullScreen = true;
            windowClass.setWindowLayoutFullScreen(isLayoutFullScreen).then(() => {
              console.info('Succeeded in setting the window layout to full-screen mode.');
            }).catch((err: BusinessError) => {
              console.error(`Failed to set the window layout to full-screen mode. Code is ${err.code}, message is ${err.message}`);
              return;
            });
      
            // 2.获取布局避让遮挡的区域
            let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
            let avoidArea = windowClass.getWindowAvoidArea(type);
            let bottomRectHeight = avoidArea.bottomRect.height; // 获取到导航条区域的高度
            AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
      
            type = window.AvoidAreaType.TYPE_SYSTEM; // 以状态栏避让为例
            avoidArea = windowClass.getWindowAvoidArea(type);
            let topRectHeight = avoidArea.topRect.height; // 获取状态栏区域高度
            AppStorage.setOrCreate('topRectHeight', topRectHeight);
      
            // 3.注册监听函数,动态获取避让区域数据
            windowClass.on('avoidAreaChange', (data) => {
              if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
                let topRectHeight = data.area.topRect.height;
                AppStorage.setOrCreate('topRectHeight', topRectHeight);
              } else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
                let bottomRectHeight = data.area.bottomRect.height;
                AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
              }
            });
            console.info('Succeeded in loading the content.');
          });
        }
      }
      
      import { CustomTabContent } from '../component/CustomTabContent';
      
      @Entry
      @Component
      struct Index {
        @State barNames: string[] = ['首页', '推荐', '发现', '我的'];
        @StorageProp('bottomRectHeight')
        bottomRectHeight: number = 0;
        @StorageProp('topRectHeight')
        topRectHeight: number = 0;
      
        build() {
          Tabs({ barPosition: BarPosition.End }) {
            ForEach(this.barNames, (item: string) => {
              CustomTabContent({content: item + '的内容', bar: item})
            }, (item: string) => item)
          }
          .backgroundColor(Color.Blue)
          .height('100%')
          .width('100%')
          .padding({ top: px2vp(this.topRectHeight), bottom: px2vp(this.bottomRectHeight) })
        }
      }
      
      @Component
      export struct CustomTabContent {
        content: string = '';
        bar: string = '';
      
      
        build() {
          TabContent() {
            Column() {
              Text(this.content).fontSize(30)
            }
            .justifyContent(FlexAlign.Start)
            .height('100%')
            .width('100%')
          }
          .tabBar(this.bar)
        }
      }
      
    • 隐藏避让区方案:

      export default class EntryAbility extends UIAbility {
        onWindowStageCreate(windowStage: window.WindowStage): void {
          console.info('Ability onWindowStageCreate');
      
          windowStage.loadContent('pages/Index', (err) => {
            if (err.code) {
              console.error(`Failed to load the content. Cause: ${err}`);
              return;
            }
      
            // 获取应用主窗口
            let windowClass: window.Window = windowStage.getMainWindowSync();
      
            // 1.设置窗口全屏
            let isLayoutFullScreen = true;
            windowClass.setWindowLayoutFullScreen(isLayoutFullScreen).then(() => {
              console.info('Succeeded in setting the window layout to full-screen mode.');
            }).catch((err: BusinessError) => {
              console.error(`Failed to set the window layout to full-screen mode. Code is ${err.code}, message is ${err.message}`);
              return;
            });
      
            // 2.设置状态栏隐藏
            windowClass.setSpecificSystemBarEnabled('status', false).then(() => {
              console.info('Succeeded in setting the status bar to be invisible.');
            }).catch((err: BusinessError) => {
              console.error(`Failed to set the status bar to be invisible. Code is ${err.code}, message is ${err.message}`);
            });
      
            // 3.设置导航条隐藏
            windowClass.setSpecificSystemBarEnabled('navigationIndicator', false).then(() => {
              console.info('Succeeded in setting the navigation indicator to be invisible.');
            }).catch((err: BusinessError) => {
              console.error(`Failed to set the navigation indicator to be invisible. Code is ${err.code}, message is ${err.message}`);
            });
      
            console.info('Succeeded in loading the content.');
          });
        }
      }
      
      import { CustomTabContent } from '../component/CustomTabContent';
      
      @Entry
      @Component
      struct Index {
        @State barNames: string[] = ['首页', '推荐', '发现', '我的'];
      
        build() {
          Tabs({ barPosition: BarPosition.End }) {
            ForEach(this.barNames, (item: string) => {
              CustomTabContent({content: item + '的内容', bar: item})
            }, (item: string) => item)
          }
          .backgroundColor(Color.Blue)
        }
      }
      
      @Component
      export struct CustomTabContent {
        content: string = '';
        bar: string = '';
      
      
        build() {
          TabContent() {
            Column() {
              Text(this.content).fontSize(30).padding(50)
            }
            .justifyContent(FlexAlign.Center)
            .height('100%')
            .width('100%')
          }
          .tabBar(this.bar)
        }
      }
      
  • 组件安全区方案

    • 状态栏和导航条颜色相同场景,可以通过设置窗口的背景色来实现沉浸式效果;

      export default class EntryAbility extends UIAbility {
        onWindowStageCreate(windowStage: window.WindowStage): void {
          console.info('Ability onWindowStageCreate');
      
          windowStage.loadContent('pages/Index', (err) => {
            if (err.code) {
              console.error(`Failed to load the content. Cause: ${err}`);
              return;
            }
      
            // 设置全窗颜色和应用元素颜色一致
            windowStage.getMainWindowSync().setWindowBackgroundColor('#008000');
            console.info('Succeeded in loading the content.');
          });
        }
      }
      
    • 状态栏和导航条颜色不相同场景,可以使用expandSafeArea属性扩展安全区域属性进行调整;

      @Entry
      @Component
      struct Index {
        build() {
          Column() {
            Row() {
              Text('Top Row').fontSize(40).textAlign(TextAlign.Center).width('100%')
            }
            .backgroundColor('#F08080')
            // 设置顶部绘制延伸到状态栏
            .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
      
            Row() {
              Text('ROW2').fontSize(40)
            }.backgroundColor(Color.Orange).padding(20)
      
            Row() {
              Text('ROW3').fontSize(40)
            }.backgroundColor(Color.Orange).padding(20)
      
            Row() {
              Text('ROW4').fontSize(40)
            }.backgroundColor(Color.Orange).padding(20)
      
            Row() {
              Text('ROW5').fontSize(40)
            }.backgroundColor(Color.Orange).padding(20)
      
            Row() {
              Text('Bottom Row').fontSize(40).textAlign(TextAlign.Center).width('100%')
            }
            .backgroundColor(Color.Orange)
            // 设置底部绘制延伸到导航条
            .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
          }
          .width('100%').height('100%').alignItems(HorizontalAlign.Center)
          .backgroundColor('#008000')
          .justifyContent(FlexAlign.SpaceBetween)
        }
      }
      

如果是大部分应用界面与状态栏、导航条风格不一致需要调整的,建议采用全屏布局的方案处理,并对游戏、电影等应用场景采用隐藏避让区的方式处理;对于小部分风格不一致的场景,采用组件安全区方案处理。

更多关于HarmonyOS鸿蒙Next中为什么用5.0之后顶部和底部有一片空白的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


那是状态栏和导航栏的区域,可以把页面设置为全屏模式就可以去掉。

应该是顶部状态栏和底部导航栏的占位高度,和window是否开启沉浸式有关,文档里搜索setWindowLayoutFullScreen查看使用方法,此方法适合将所有页面均设为沉浸式使用。

1楼说的expandSafeArea适合选择性的将某个界面启用沉浸式。

上下的空白可以使用 expandSafeArea() 去除

在HarmonyOS鸿蒙Next中,顶部和底部出现空白可能是由于系统UI设计或应用布局适配问题。鸿蒙Next采用了新的UI框架和设计规范,可能导致部分应用在5.0版本后未完全适配新的布局规则。系统可能为状态栏、导航栏或其他系统组件预留了空间,以确保内容不被遮挡。开发者需要根据鸿蒙Next的设计指南调整应用布局,确保界面元素正确显示。

在HarmonyOS鸿蒙Next 5.0中,顶部和底部出现空白可能是由于系统默认启用了“沉浸式状态栏”和“导航栏”功能。这些空白区域是为了确保应用内容不会被系统状态栏和导航栏遮挡,提供更好的用户体验。开发者可以通过调整布局或使用系统提供的API来优化界面显示,确保应用内容与系统UI元素协调一致。

回到顶部