【每日学点HarmonyOS Next知识】顶部状态栏、文本最大行数后缀、弹窗背景、状态栏颜色、导航

1、HarmonyOS 应用把顶部系统状态栏信息完全覆盖了?
复制代码
//设置窗口全屏模式时导航栏、状态栏的可见模式(需全部显示,该参数设置为['status', 'navigation'],不设置,则默认不显示)
let names: Array<'status' | 'navigation'> = [];
windowClass.setWindowSystemBarEnable(names, (err: BusinessError) => {
  let errCode: number = err.code;
  if (errCode) {
    console.error('Failed to set the system bar to be visible. Cause:' + JSON.stringify(err));
    return;
  }
  console.info('Succeeded in setting the system bar to be visible.');
});
console.info('Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));

参考文档:https://developer.huawei.com/consumer/cn/doc/app/50106

设置全屏沉浸式后可以使用getWindowAvoidArea()接口获取布局遮挡区域,在组件中根据避让区域返回值自行设置:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-develop-apply-immersive-effects-V5

如果需要显示状态栏和导航栏的话,是要每个页面都去做规避的,如果可以不想显示状态和导航栏可以通过setSpecificSystemBarEnabled来隐藏:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-window-V5

关于窗口内容需要规避区域的类型枚举:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-window-V5

2、HarmonyOS 怎么处理文本显示最大行数后 追加...全文的问题?

用计算的方式算出每个字的宽度,累加,但是有时计算不准确,我们文字内部含有表情,然后有时系统一些文字也会折行,用了wordBreak(WordBreak.BREAK_ALL)这个api 不折行显示了,但是还是计算不准确,延后显示。

  1. 首先使用measure.measureText()方法测量实际文本宽度,接着使用display.getAllDisplays()获取手机屏幕宽度,然后用"屏幕宽度 * 最大行数 * 组件宽度比例"的结果和"实际文本宽度"进行比较大小,判断是否需要"...展开全文";

  2. 当需要"...展开全文"时,只展示maxLines属性设置的固定高度的文本内容,当点击"...展开全文"时将该文本改成"...收起"并添加curves.springMotion曲线动画,同时在animateTo的显示动效的闭包函数中将maxLines属性值修改为-1使得该属性无效;

  3. 当需要"...收起"时,将collapseText的值改为"...展开全文",并设置收起动画。

    // MyText.ets
    import measure from '@ohos.measure'
    import curves from '@ohos.curves';
    import { BusinessError } from '@ohos.base';
    import display from '@ohos.display';

    @Component
    @Preview
    export struct MyText {
    // 长文本
    @State longMessage: string = "ArkTS提供了简洁自然的声明式语法、组件化机制、数据-UI自动关联等能力,实现了贴近自然语言,书写效率更高的编程方式,为开发者带来易学、易懂、简洁开发的优质体验。"
    // 最大显示行数
    @State lines: number = 3;
    // 长文本状态(展开 or 收起)
    @State collapseText: string = '...展开全文'
    // 屏幕宽度(单位px)
    screenWidth: number = 0;
    // 是否需要显示"展开"字样(注:当文本长度较短时就不需要"展开")
    @State isExpanded: boolean = false
    // 测量文本宽度(单位px)
    @State textWidth: number = measure.measureText({
    textContent: this.longMessage,
    fontSize: 15
    })
    // 获取当前所有的display对象
    promise: Promise<Array<display.Display>> = display.getAllDisplays()

    aboutToAppear() {
    console.log(文本宽度为:${this.textWidth})
    this.promise.then((data: Array<display.Display>) => {
    console.log(所有的屏幕信息:${JSON.stringify(data)})
    //单位为像素
    this.screenWidth = data[0]["width"]
    // 屏幕宽度 * 最大行数 * 组件宽度比例 和 文字测量宽度
    this.isExpanded = this.screenWidth * this.lines * 0.8 <= this.textWidth
    }).catch((err: BusinessError) => {
    console.error(Failed to obtain all the display objects. Code: ${JSON.stringify(err)})
    })
    }

    build() {
    Row() {
    Column() {
    if (this.isExpanded) {
    Stack({ alignContent: Alignment.BottomEnd }) {
    Text(this.longMessage)
    .fontSize(15)
    .fontColor(Color.Black)
    .maxLines(this.lines)
    .width('80%')
    Row() {
    Text(this.collapseText)
    .fontSize(15)
    .backgroundColor(Color.White)
    }
    .justifyContent(FlexAlign.End)
    .onClick(() => {
    if (this.collapseText == '...展开全文') {
    this.collapseText = '...收起';
    // 展开动画
    animateTo({
    duration: 150,
    curve: curves.springMotion(0.5, 0.8),
    }, () => {
    this.lines = -1; // 使得设置的最大行属性无效
    })
    } else {
    this.collapseText = '...展开全文';
    // 收起动画
    animateTo({
    duration: 100,
    curve: Curve.Friction,
    }, () => {
    this.lines = 3; // 只显示3行
    })
    }
    })
    }
    }
    else {
    Text(this.longMessage)
    .fontSize(15)
    .fontColor(Color.Black)
    }
    }
    .width('100%')
    }
    .height('100%')
    }
    }

    // Index.ets
    import { MyText } from './MyText'
    @Entry
    @Component
    struct Index {
    build(){
    Column(){
    MyText()
    }
    }
    }

3、HarmonyOS 组件绑定popup弹窗,如何将弹窗背景设置成透明状态?

popupColor设置成透明但弹窗还是默认白色背景

复制代码
Image($r("app.media.gray_tips_icon"))
  .width($r("app.string.dp15"))
  .height($r("app.string.dp15"))
  .onClick(() => {
    this.tipPopup = !this.tipPopup
  })
  .bindPopup(this.tipPopup, {
    builder: this.popupBuilder(),
    placement: Placement.Top,
    mask: false,
    popupColor: Color.Transparent,
    enableArrow: true,
    showInSubWindow: false,
    onStateChange: (e) => {
      if (!e.isVisible) {
        this.tipPopup = false
      }
    },
    arrowOffset: $r("app.string.dp50"),
    offset: { x: $r("app.string.dp20") },
    radius: $r("app.string.dp8")
  })

参考代码:

复制代码
@Entry
@Component
struct PopupExample {
  @State handlePopup: boolean = false
  @Builder popupBuilder(){
    Text('气泡的内容')
  }

  build() {
    Column() {
      Button('PopupOptions')
        .onClick(() => {
          this.handlePopup = !this.handlePopup
        })
        .bindPopup(this.handlePopup, {
          builder: this.popupBuilder(),//内容
          placement:Placement.Bottom, // 气泡的弹出位置
          maskColor: Color.Transparent,
          popupColor:Color.Transparent, // 气泡的背景色
          backgroundBlurStyle: BlurStyle.NONE,
          shadow: {
            radius:0
          },
          onStateChange: (e) => {
            console.info(JSON.stringify(e.isVisible))
            if (!e.isVisible) {
              this.handlePopup = false
            }
          }
        })
    }
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .width('100%')
    .padding({ top: 5 })
    .backgroundColor(Color.Pink)
  }
}

Navigation组件设置.hideNavBar(true),调用pushPathByName打开首页和二级页面首页的navBar隐藏,符合预期二级页面的navBar未隐藏且有返回按钮,有办法隐藏吗

设置NavDestination().hideTitleBar(true)

5、HarmonyOS 每个页面状态栏背景颜色和字体颜色不一样,怎么动态设置每个页面的沉浸式状态栏?

目前尝试在每个页面生命周期onPageShow和aboutToApear中调用以上两个方法,但是有些页面颜色还是没变过来,出现了问题,生命周期中无法正确改变系统状态栏颜色

参考代码:

复制代码
修改了一下代码
参考:
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { WindowManager } from '../WindowManager';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    hilog.info(0x0000, 'testTag', JSON.stringify(this.context), 'context-tag');

    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    windowStage.loadContent('enablement/enablement', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }

      let windowClass = windowStage.getMainWindowSync();
      AppStorage.setOrCreate('windowClass', windowClass);

      WindowManager.enableFullScreen()
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
      // let windowClass: window.Window = windowStage.getMainWindowSync(); //获取应用主窗口
      // windowClass.setWindowLayoutFullScreen(true)
      // let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; //以导航条避让为例
      // let avoidArea = windowClass.getWindowAvoidArea(type);
      // let bottomRectHeight = px2vp(avoidArea.bottomRect.height); //获取到导航条区域的高度
      // AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight) //将高度转成vp,存到AppStorage中方便其它页面获取高度
      // let area = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
      // let statusBarHeight = px2vp(area.topRect.height) //状态栏高度
      // AppStorage.setOrCreate('statusBarHeight', statusBarHeight) //将高度转成vp,存到AppStorage中方便其它页面获取高度
      // hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
      // windowClass.setWindowSystemBarEnable(['status', 'navigation'])
      // windowClass.setWindowSystemBarProperties({
      //   statusBarColor: "#FFFFFF",
      //   statusBarContentColor: '#FFFFFF'
      // })

    });
  }

  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

//WindowManager.ets

import
{
  window
}
from
'@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { LogUtil } from '@pura/harmony-utils';


// 设置沉浸式工具类
export class WindowManager {
  private static readonly TAG: string = "WindowManager---"

  //开启沉浸式全屏模式
  static enableFullScreen() {
    let win: window.Window = AppStorage.get('windowClass')!
    win.setWindowLayoutFullScreen(true) //使用setWindowLayoutFullScreen设置true开启沉浸式模式
    const topArea = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM) //使用getWindowAvoidArea方法获取到安全区域的高度
    let topHeight = px2vp(topArea.topRect.height)
    AppStorage.setOrCreate('topHeight', topHeight) //将高度转成vp,存到AppStorage中方便其它页面获取高度
    const bottomArea = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
    let bottomHeight = px2vp(bottomArea.bottomRect.height)
    AppStorage.setOrCreate('bottomHeight', bottomHeight) //将高度转成vp,存到AppStorage中方便其它页面获取高度
    LogUtil.error(WindowManager.TAG, `topHeight:${topHeight},,,bottomHeight:${bottomHeight}`)
  }

  //关闭沉浸式模式
  static disableFullScreen() {
    let win: window.Window = AppStorage.get('windowClass')!
    win.setWindowLayoutFullScreen(false) //使用setWindowLayoutFullScreen设置false关闭沉浸式模式
    AppStorage.setOrCreate('topHeight', 0) //将高度重置为零
  }

  static settingStatusBarLight() {
    let win: window.Window = AppStorage.get('windowClass')!
    win.setWindowSystemBarProperties({ statusBarContentColor: '#FFFFFF' }) //设置安全区字体颜色为白色

  }

  static settingStatusBarDark() {
    let win: window.Window = AppStorage.get('windowClass')!
    win.setWindowSystemBarProperties({ statusBarContentColor: '#000000' }) //设置安全区字体颜色为黑色
  }

  static async keepScreenOn(isKeepScreenOn: boolean) {
    let win: window.Window = AppStorage.get('windowClass')!
    let promise = win.setWindowKeepScreenOn(isKeepScreenOn)
    promise?.then(() => {
      LogUtil.error(WindowManager.TAG, `${isKeepScreenOn ? "打开" : "关闭"}屏幕常亮成功`)
    }).catch((error: BusinessError) => {
      LogUtil.error(WindowManager.TAG,
        `${isKeepScreenOn ? "打开" : "关闭"}屏幕常亮异常,error:${JSON.stringify(error)}`)
    });

  }

  private static async setWindowBrightness(brightness: number) {
    let win: window.Window = AppStorage.get('windowClass')!

    let promise = win.setWindowBrightness(brightness)
    promise?.then(() => {
      LogUtil.error(WindowManager.TAG, "设置屏幕亮度成功")
    }).catch((error: BusinessError) => {
      LogUtil.error(WindowManager.TAG, "设置屏幕亮度异常,error:" + JSON.stringify(error))
    });

  }

  static setWindowMaxBrightness() {
    WindowManager.setWindowBrightness(1)
  }

  static setWindowDefaultBrightness() {
    WindowManager.setWindowBrightness(-1)
  }
}
相关推荐
小小小小小星2 小时前
鸿蒙开发之ArkUI框架进阶:从声明式范式到跨端实战
harmonyos·arkui
鸿蒙小灰2 小时前
鸿蒙开发对象字面量类型标注的问题
harmonyos
鸿蒙先行者3 小时前
鸿蒙Next不再兼容安卓APK,开发者该如何应对?
harmonyos
YF云飞5 小时前
.NET 在鸿蒙系统(HarmonyOS Next)上的适配探索与实践
华为·.net·harmonyos
Quarkn9 小时前
鸿蒙原生应用ArkUI之自定义List下拉刷新动效
list·harmonyos·arkts·鸿蒙·arkui
AlbertZein10 小时前
HarmonyOS5 凭什么学鸿蒙 —— Context详解
harmonyos
whysqwhw18 小时前
鸿蒙音频播放方式总结
harmonyos
whysqwhw18 小时前
鸿蒙音频录制方式总结
harmonyos
zhanshuo20 小时前
HarmonyOS 实战:用 @Observed + @ObjectLink 玩转多组件实时数据更新
harmonyos
zhanshuo20 小时前
鸿蒙任务调度机制深度解析:优先级、时间片、多核与分布式的流畅秘密
harmonyos