当前位置: 首页 > article >正文

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

【每日学点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
@Component
struct 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.ets
import { PageTwo } from './pageTwo';

export class NavParam {
  dialogHeightChangeBack?: (dialogHeight: number) => void

  constructor( dialogHeightChangeBack?: (dialogHeight: number) => void) {
    this.dialogHeightChangeBack = dialogHeightChangeBack
  }
}


@Entry
@Component
struct 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

@Component
export 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.ets
build{
  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
@Component
struct 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%')
  }
}

http://www.kler.cn/a/572027.html

相关文章:

  • 【C++】为什么C++的构造函数不能为虚函数,折钩函数可以为虚函数
  • ChatVLA:基于视觉-语言-动作模型的统一多模态理解与机器人控制
  • python和pycharm安装教程
  • 云服数据存储接口:CloudSever
  • JavaEE_多线程(一)
  • C++中的无锁编程
  • Python Cookbook-3.1 计算昨天和明天的日期
  • 详细分析KeepAlive的基本知识 并缓存路由(附Demo)
  • JavaWeb基础专项复习6(2)——AJAX补充
  • [leetcode]704.二分查找-简单
  • 【Canny 边缘检测详细讲解】
  • 【ORACLE】ORACLE19C在19.13版本前的一个严重BUG-24761824
  • 统计URL出现层级及次数
  • 2025-03-04 学习记录--C/C++-C语言 判断是否是素数
  • C# .NETCore ZipArchive 处理大容量文件导致内存占用高的问题
  • 【YOLO12全网首发】训练+测试行人摔倒
  • json介绍、python数据和json数据的相互转换
  • 华为 VRP 系统简介配置SSH,TELNET远程登录
  • Kubernetes Pod 管理及优化
  • 利用出书策略结合定制开发开源AI智能名片S2B2C商城小程序获取私域流量的探索