写点什么

【每日学点 HarmonyOS Next 知识】getContext 问题、清除 Web 缓存、弹层的点击事件透传、去除间隙、侧滑菜单设置

作者:轻口味
  • 2025-03-07
    北京
  • 本文字数:7836 字

    阅读完需:约 26 分钟

【每日学点HarmonyOS Next知识】getContext问题、清除Web缓存、弹层的点击事件透传、去除间隙、侧滑菜单设置

1、HarmonyOS getContext()获取不到?

在两个不同的页面分别使用 bindPopup 与 bindSheet 弹出相同的弹窗,点击弹窗中的按钮跳转 H5 页面,其中 bindPopup 会闪退,报错Error message:Cannot read property resourceManager of undefined SourceCode:const resourceManager = context.resourceManager; getContext()获取不到。而 bindSheet 正常打开 h5 页面


getContext()获取不到,导致 resourceManager 为 undefined 在 ability 内使用 this.context 在 ui 侧可使用 getcontext

2、HarmonyOS 如何清除 Web 缓存?

如何清除 Web 组件加载网页后产生的资源(图片等)的缓存


可以使用 removeCache()方法。参考地址:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-webview-V5#removecache


removeCache(clearRom: boolean): void 清除应用中的资源缓存文件,此方法将会清除同一应用中所有 webview 的缓存文件。


可以通过在 data/storage/el2/base/cache/web/Cache 目录下查看 Webview 的缓存。

3、HarmonyOS 弹层的点击事件透传处理?

实现一套各个页面均可弹层的功能,涉及到弹层的点击事件透传处理希望可以获取到点击的位置,弹层内的像素点,并获取到透明度,来判断点击事件是否需要透传到底部场景。当前根据点击坐标获取透明度的整体链路,因组件截图 api 是异步接口,事件拦截需要同步接口,无法达成整体链路。


参考代码:


@Entry@Componentstruct HitTestPage {  @State message: string = 'Hello World';
build() { Stack() { Column() .onTouch((event: TouchEvent)=> { if (event.type == TouchType.Down) { console.info("点击了:底部的界面") } }) .height('100%') .width('100%') .backgroundColor(Color.Green) Column() { Text() .backgroundColor(Color.Black) .onTouch((event: TouchEvent)=> { event.stopPropagation() if (event.type == TouchType.Down) { console.info("点击了:文本") } }) .height(100) .width(100) } .onTouch((event: TouchEvent)=> { if (event.type == TouchType.Down) { console.info("点击了:上面的界面") } }) .hitTestBehavior(HitTestMode.Transparent) .backgroundColor(Color.Transparent) .height('100%') .width('100%') } .height('100%') .width('100%') }}
复制代码


//Index.etsimport { PageTwo } from './pageTwo';
export class NavParam { dialogHeightChangeBack?: (dialogHeight: number) => void
constructor( dialogHeightChangeBack?: (dialogHeight: number) => void) { this.dialogHeightChangeBack = dialogHeightChangeBack }}

@Entry@Componentstruct Index { @State message: string = 'Hello World'; @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack() @StorageLink("windowHeight") windowHeight: number = 0 @State contentHeight: number = 100; private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
@Builder PageMap(name: string, param: NavParam) { if (name === 'pageTwo') { PageTwo({dialogHeightChangeBlock: param.dialogHeightChangeBack}); } }
aboutToAppear() { console.info("testTag: 当前windowHeight" + this,this.windowHeight); this.contentHeight = px2vp(this.windowHeight); }
build() { Navigation(this.pageInfos) { Column() { Row().height(50) Button("pageOne") .fontSize(30) .type(ButtonType.Capsule) .fontWeight(FontWeight.Bold) .onClick(() => { this.pageInfos.pushPath({ name: 'pageTwo', param: new NavParam( (dialogHeight: number) => { if (dialogHeight == 0) { animateTo({ duration: 250 }, () => { this.contentHeight = px2vp(this.windowHeight); }) } else { this.contentHeight = px2vp(this.windowHeight) - dialogHeight; } }) }); })
List({ space: 20, initialIndex: 0 }) { ForEach(this.arr, (item: number) => { ListItem() { Text('' + item) .width('100%').height(100).fontSize(16) .textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF) } }, (item: string) => item) } .listDirection(Axis.Vertical) // 排列方向 .scrollBar(BarState.Off) .friction(0.6) .divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线 .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring .width('90%')
} .justifyContent(FlexAlign.Center) .width('100%') .height(this.contentHeight) .hitTestBehavior(HitTestMode.Transparent) .onTouch((event: TouchEvent) => { if (event.type == TouchType.Down) { console.info('事件穿透:colume点击了') } }) } .navDestination(this.PageMap) .onTouchIntercept((event: TouchEvent) => { if (event.type == TouchType.Down) { console.info('事件穿透:navigation点击了') } return HitTestMode.Transparent }) }}
//PageTwo.ets
@Componentexport struct PageTwo { @State isShow: boolean = true; gravity: Alignment = Alignment.Bottom transitionEdge: TransitionEdge = TransitionEdge.BOTTOM @Consume('pageInfos') pageInfos: NavPathStack; @State gestureHeight: number = 500; dialogHeightChangeBlock?: (dialogHeight: number) => void; private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] scrollOffsetY: number = 0; private scrollerForList: Scroller = new Scroller() @State canHandleScroll: boolean = true;
aboutToAppear() { this.callBackHeight(this.gestureHeight); }
callBackHeight(height: number) { if (this.dialogHeightChangeBlock) { this.dialogHeightChangeBlock!(height); } }
build() { NavDestination() { //背景层 Stack({ alignContent: this.gravity }) { //内容区 Stack({ alignContent: this.gravity }) { if (this.isShow) { //手势层 Stack({ alignContent: Alignment.Top }) { Column() { List({ space: 20, initialIndex: 0, scroller: this.scrollerForList }) { ForEach(this.arr, (item: number) => { ListItem() { Text('' + item) .width('100%') .height(100) .fontSize(16) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } }, (item: string) => item) } .enableScrollInteraction(this.canHandleScroll) .listDirection(Axis.Vertical) // 排列方向 .scrollBar(BarState.Off) .friction(0.6) .divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线 .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring .onScroll((scrollOffset: number, scrollState: ScrollState) => { this.scrollOffsetY += scrollOffset; console.info("list: y偏移量 " + this.scrollOffsetY);
if (this.scrollOffsetY <= 0) { this.scrollerForList.scrollTo({xOffset:0,yOffset:0,animation:false}); this.scrollOffsetY = 0; this.canHandleScroll = false; } })
.height('100%') .width('100%') } } .borderRadius(6) .transition(TransitionEffect.move(this.transitionEdge).animation({ duration: 250, curve: Curve.Smooth })) .position({ x: 0, y: 0 }) .height("100%") .width("100%") .clip(true) .backgroundColor(Color.White) } } .width("100%") .height(this.gestureHeight) .parallelGesture( PanGesture({ direction: PanDirection.Vertical, fingers: 1 }) .onActionUpdate((event: GestureEvent) => { if (!this.canHandleScroll) { console.info("testTag: y偏移量 " + event.offsetY); let temHeight = 500; temHeight -= event.offsetY; if (temHeight >= 500) { this.gestureHeight = 500; } else { this.gestureHeight = temHeight; } this.callBackHeight(this.gestureHeight); } }) .onActionEnd((event: GestureEvent) => { if (!this.canHandleScroll) { console.info("testTag: 动画结束y偏移量 " + event.offsetY); let temHeight = 500; temHeight -= event.offsetY; if (temHeight < 250) { this.closeDialogAction() } else if (temHeight >= 250 && temHeight < 500) { let duration = (500 - temHeight) / 500.0 * 250.0; animateTo({ duration: duration }, () => { this.gestureHeight = 500; this.callBackHeight(this.gestureHeight); }) } this.canHandleScroll = true; } }) ) } .onClick(() => { // this.closeDialogAction() }) .onTouchIntercept((event: TouchEvent) => { if (event.type == TouchType.Down) { console.info('事件穿透:stack点击了') } return HitTestMode.Transparent }) .width('100%') .height('100%') .backgroundColor('#33000000') } .onBackPressed(() => { this.closeDialogAction() return true }) .hitTestBehavior(HitTestMode.Transparent) .onTouch((event: TouchEvent) => { if (event.type == TouchType.Down) { console.info('事件穿透:dialog点击了') } }) .hideTitleBar(true) .mode(NavDestinationMode.DIALOG) }
closeDialogAction() { this.isShow = false; this.callBackHeight(0); animateTo({ duration: 100, delay: 250, onFinish: () => { this.pageInfos.pop() } }, () => { }) }}
//EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';import { window } from '@kit.ArkUI';
async function enterImmersion(windowClass: window.Window) {
AppStorage.setOrCreate<number>('windowHeight', windowClass.getWindowProperties().windowRect.height) AppStorage.setOrCreate<number>('windowWidth', windowClass.getWindowProperties().windowRect.width)
// 监听窗口高度变化 windowClass.on('windowSizeChange', (size)=> { AppStorage.setOrCreate<number>('windowHeight', size.height) AppStorage.setOrCreate<number>('windowWidth', size.width) })
// 设置窗口布局为沉浸式布局 await windowClass.setWindowLayoutFullScreen(true) await windowClass.setWindowSystemBarEnable(["status", "navigation"]) // 设置状态栏和导航栏的背景为透明 await windowClass.setWindowSystemBarProperties({ navigationBarColor: "#00000000", statusBarColor: "#00000000", })}

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'); }
async onWindowStageCreate(windowStage: window.WindowStage) { // Main window is created, set main page for this ability hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
let windowClass:window.Window = await windowStage.getMainWindow() await enterImmersion(windowClass)
windowStage.loadContent('pages/Index', (err) => { if (err.code) { hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); return; } hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); }); }
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'); }}
复制代码

4、HarmonyOS 如何去除间隙?

如何去除虚拟键盘与自定义输入框 dialog 之间的间隙


之所以设置安全距离,是因为自定义弹窗仅适用于简单提示场景,不能替代页面使用。由于弹窗存在完全避让输入法行为,即在软键盘弹出时,会自动向上抬起软键盘高度,因此如果弹窗高度过大时,可能会导致部分区域不可见。弹窗避让软键盘时,与软键盘之间存在 16vp 的安全间距。 结合文档说法,可以手动在软键盘弹起时设置 offset:{y:16}来抵消安全距离。


参考 demo:


//CustomDialog.etsbuild{  Column(){    TextArea({      text: "",      placeholder: 'The text area can hold an unlimited amount of text. input your word...',      controller: this.textController    })      .height(200)      .width("100%")  }  //todo 需要在 TextArea的外层组件设置 offset 来抵消安全距离  .offset({    y:16  })}//规格选择页面控制器customDialogController: CustomDialogController = new CustomDialogController({  builder: SpecificationsCustomDialog({
}), alignment: DialogAlignment.Bottom, customStyle: true, autoCancel: false, //这里设置dy: -16,会将弹窗抬起来 offset: { dx: 0, dy: -16 }});
复制代码

5、HarmonyOS ListItem 侧滑菜单动态设置?

有一个 list 列表,列表项 item 有侧滑菜单,但是编辑状态下又没有侧滑菜单,想通过一个开关动态设置侧滑菜单


参考 demo:


@Entry@Componentstruct ListItemExample2 {  @State arr: number[] = [0, 1, 2, 3, 4]  @State enterEndDeleteAreaString: string = "not enterEndDeleteArea"  @State exitEndDeleteAreaString: string = "not exitEndDeleteArea"  @State isShow:boolean = true;
@Builder itemEnd() { Row() { Button("Delete").margin("4vp") Button("Set").margin("4vp") }.padding("4vp").justifyContent(FlexAlign.SpaceEvenly) }
build() { Column() { Button("点击").onClick(()=>{ this.isShow=!this.isShow console.log(this.isShow+"111111111") }) List({ space: 10 }) { ForEach(this.arr, (item: number) => { ListItem() { Text("item" + item) .width('100%') .height(100) .fontSize(16) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } .transition({ type: TransitionType.Delete, opacity: 0 }) .swipeAction({ end: this.isShow?{ builder: () => { this.itemEnd() }, onAction: () => { animateTo({ duration: 1000 }, () => { let index = this.arr.indexOf(item) this.arr.splice(index, 1) }) }, actionAreaDistance: 56, onEnterActionArea: () => { this.enterEndDeleteAreaString = "enterEndDeleteArea" this.exitEndDeleteAreaString = "not exitEndDeleteArea" }, onExitActionArea: () => { this.enterEndDeleteAreaString = "not enterEndDeleteArea" this.exitEndDeleteAreaString = "exitEndDeleteArea" } }:undefined }) }, (item: string) => item) } Text(this.enterEndDeleteAreaString).fontSize(20) Text(this.exitEndDeleteAreaString).fontSize(20) } .padding(10) .backgroundColor(0xDCDCDC) .width('100%') .height('100%') }}
复制代码


发布于: 刚刚阅读数: 5
用户头像

轻口味

关注

🏆2021年InfoQ写作平台-签约作者 🏆 2017-10-17 加入

Android、音视频、AI相关领域从业者。 欢迎加我微信wodekouwei拉您进InfoQ音视频沟通群 邮箱:qingkouwei@gmail.com

评论

发布
暂无评论
【每日学点HarmonyOS Next知识】getContext问题、清除Web缓存、弹层的点击事件透传、去除间隙、侧滑菜单设置_HarmonyOS_轻口味_InfoQ写作社区