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 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)
}
}