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 不折行显示了,但是还是计算不准确,延后显示。
- 首先使用measure.measureText()方法测量实际文本宽度,接着使用display.getAllDisplays()获取手机屏幕宽度,然后用“屏幕宽度 * 最大行数 * 组件宽度比例”的结果和“实际文本宽度”进行比较大小,判断是否需要“…展开全文”;
- 当需要“…展开全文”时,只展示maxLines属性设置的固定高度的文本内容,当点击“…展开全文”时将该文本改成“…收起”并添加curves.springMotion曲线动画,同时在animateTo的显示动效的闭包函数中将maxLines属性值修改为-1使得该属性无效;
- 当需要“…收起”时,将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)}
}
4、HarmonyOS Navigation组件hideNavBar问题?
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 abilityhilog.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 resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}//WindowManager.etsimport
{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)}
}