写点什么

【每日学点 HarmonyOS Next 知识】网页获取高度、行为菜单底部布局、动画问题、Web 跨域加载图片、不随系统深色变化

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

    阅读完需:约 18 分钟

【每日学点HarmonyOS Next知识】网页获取高度、行为菜单底部布局、动画问题、Web跨域加载图片、不随系统深色变化

1、HarmonyOS Web 控件 getPageHeight()获取高度方法与网页实际高度不一样?

在 Web 的 onPageEnd()方法中调用 getWebViewController().getPageHeight() 获取的高度与网页内容实际高度不符偏小,通过 setTimeout(()=>{ let webHeight1 = this.controller.getWebViewController().getPageHeight() Logger.getInstance().error('内部控件高度 time',' webHeight:'+webHeight1+' webHeight:'+vp2px(webHeight1)) },200) 获取的高度与网页实际高度相同,有没有不需要延时的获取网页实际高度的方法?


onPageEnd 是页面加载完回调,不等于页面渲染完成,所以前后获取的高度不一样。可使用:onFirstMeaningfulPaint 文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-web-V5#ZH-CN_TOPIC_0000001847049744__onfirstmeaningfulpaint12

2、HarmonyOS promptAction.showActionMenu 接口支持布局为底部布局吗?

promptAction.showActionMenu 接口支持弹窗布局为底部布局吗?看了下文档里不能设置对其方式,并且示例里也是居中的方式。


参考 demo:


import promptAction from '@ohos.promptAction';import { BusinessError } from '@ohos.base';
function showActionMenu() { try { promptAction.showActionMenu({ title: 'Title Info', buttons: [ { text: 'item1', color: '#666666' }, { text: 'item2', color: '#000000' }, ] }, (err, data) => { if (err) { console.info('showActionMenu err: ' + err); return; } console.info('showActionMenu success callback, click button: ' + data.index); }) } catch (error) { let message = (error as BusinessError).message let code = (error as BusinessError).code console.error(`showActionMenu args error code is ${code}, message is ${message}`); } ;}
@Entry@Componentstruct Index { @State message: string = 'Hello World';
build() { RelativeContainer() { Text(this.message) .id('HelloWorld') .fontSize(50) .fontWeight(FontWeight.Bold) .alignRules({ center: { anchor: '__container__', align: VerticalAlign.Center }, middle: { anchor: '__container__', align: HorizontalAlign.Center } }) .onClick(()=>{ showActionMenu() }) } .height('100%') .width('100%') }}
复制代码

3、HarmonyOS 动画必须搭配 @State 修饰的变量才能生效吗?

一般情况下动画是需要搭配 @State 修饰的变量才能生效,以下 demo 加上 Text().width(300).height(300).backgroundColor(Color.Black)就可以做动画了


@Entry@Componentexport default struct ParticleStar {  aboutToAppear(): void {  }
build() { Stack() { Text() .width(300).height(300).backgroundColor(Color.Black) Particle({ particles: [ { emitter: { particle: { type: ParticleType.POINT, //粒子类型 config: { radius: 10//圆点半径 }, count: 500, //粒子总数 lifetime: 10000//粒子生命周期,单位ms }, emitRate: 10, //每秒发射粒子数 position: [200, 0], shape: ParticleEmitterShape.RECTANGLE//发射器形状 }, color: { range: [Color.Red, Color.Yellow], //初始颜色范围 updater: { type: ParticleUpdater.CURVE, //变化方式为曲线变化 config: [ { from: Color.White, //变化起始值 to: Color.Pink, //变化终点值 startMillis: 0, //开始时间 endMillis: 3000, //结束时间 curve: Curve.EaseIn//变化曲线 }, { from: Color.Pink, to: Color.Orange, startMillis: 3000, endMillis: 5000, curve: Curve.EaseIn }, { from: Color.Orange, to: Color.Pink, startMillis: 5000, endMillis: 8000, curve: Curve.EaseIn }, ] } }, opacity: { range: [0.0, 1.0], //粒子透明度的初始值从【0.0到1.0】随机产生 updater: { type: ParticleUpdater.CURVE, //透明度的变化方式是随机变化 config: [ { from: 0.0, to: 1.0, startMillis: 0, endMillis: 3000, curve: Curve.EaseIn }, { from: 1.0, to: 0.0, startMillis: 5000, endMillis: 10000, curve: Curve.EaseIn } ] } }, scale: { range: [0.0, 0.0], updater: { type: ParticleUpdater.CURVE, config: [ { from: 0.0, to: 0.5, startMillis: 0, endMillis: 3000, curve: Curve.EaseIn } ] } }, acceleration: { //加速度的配置,从大小和方向两个维度变化,speed表示加速度大小,angle表示加速度方向 speed: { range: [3, 9], updater: { type: ParticleUpdater.RANDOM, config: [1, 20] } }, angle: { range: [90, 90] } } } ] }).width(300).height(300) }.width("100%").height("100%").align(Alignment.Center) }}
复制代码

4、HarmonyOS Web 组件无法跨域加载图片资源?

App 访问网页,网页里面有些图片需要跨域加载,但是因为跨域无法加载显示,请问有什么方法可以解决吗?


跨域请参考以下链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/web-cross-origin-V5


为了提高安全性,ArkWeb 内核不允许 file 协议或者 resource 协议访问 URL 上下文中来自跨域的请求。因此,在使用 Web 组件加载本地离线资源的时候,Web 组件会拦截 file 协议和 resource 协议的跨域访问。可以通过方法二设置一个路径列表,再使用 file 协议访问该路径列表中的资源,允许跨域访问本地文件。当 Web 组件无法访问本地跨域资源时,开发者可以在 DevTools 控制台中看到类似以下报错信息:


Access to script at 'xxx' from origin 'xxx' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, arkweb, data, chrome-extension, chrome, https, chrome-untrusted.
复制代码


方法一为了使 Web 组件能够成功访问跨域资源,开发者应采用 http 或 https 等协议,替代原先使用的 file 或 resource 协议进行加载。其中,替代的 url 域名为自定义构造的仅供个人或者组织使用的域名,以避免与互联网上实际存在的域名产生冲突。同时,开发者需利用 Web 组件的 onInterceptRequest 方法,对本地资源进行拦截和相应的替换。


以下结合示例说明如何解决本地资源跨域访问失败的问题。其中,index.html 和 js/script.js 置于工程中的 rawfile 目录下。如果使用 resource 协议访问 index.html,js/script.js 将因跨域而被拦截,无法加载。在示例中,使用https://www.example.com/域名替换了原本的 resource 协议,同时利用 onInterceptRequest 接口替换资源,使得 js/script.js 可以成功加载,从而解决了跨域拦截的问题。


方法二


通过 setPathAllowingUniversalAccess 设置一个路径列表。当使用 file 协议访问该列表中的资源时,允许进行跨域访问本地文件。此外,一旦设置了路径列表,file 协议将仅限于访问列表内的资源(此时,fileAccess 的行为将会被此接口行为覆盖)。路径列表中的路径必须符合以下任一路径格式:


  1. 应用文件目录通过 Context.filesDir 获取,其子目录示例如下:

  2. /data/storage/el2/base/files/example

  3. /data/storage/el2/base/haps/entry/files/example

  4. 应用资源目录通过 Context.resourceDir 获取,其子目录示例如下:

  5. /data/storage/el1/bundle/entry/resource/resfile

  6. /data/storage/el1/bundle/entry/resource/resfile/example 当路径列表中的任一路径不满足上述条件时,系统将抛出异常码 401,并判定路径列表设置失败。若设置的路径列表为空,file 协议的可访问范围将遵循 fileAccess 的规则,具体示例如下。


// main/ets/pages/Index.etsimport { webview } from '@kit.ArkWeb';import { BusinessError } from '@kit.BasicServicesKit';
@Entry@Componentstruct WebComponent { controller: WebviewController = new webview.WebviewController();
build() { Row() { Web({ src: "", controller: this.controller }) .onControllerAttached(() => { try { // 设置允许可以跨域访问的路径列表 this.controller.setPathAllowingUniversalAccess([ getContext().resourceDir, getContext().filesDir + "/example" ]) this.controller.loadUrl("file://" + getContext().resourceDir + "/index.html") } catch (error) { console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); } }) .javaScriptAccess(true) .fileAccess(true) .domStorageAccess(true) } }}
复制代码


<!-- main/resource/rawfile/index.html --><!DOCTYPE html><html lang="en">
<head> <meta charset="utf-8"> <title>Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover"> <script> function getFile() { var file = "file:///data/storage/el1/bundle/entry/resources/resfile/js/script.js"; // 使用file协议通过XMLHttpRequest跨域访问本地js文件。 var xmlHttpReq = new XMLHttpRequest(); xmlHttpReq.onreadystatechange = function(){ console.log("readyState:" + xmlHttpReq.readyState); console.log("status:" + xmlHttpReq.status); if(xmlHttpReq.readyState == 4){ if (xmlHttpReq.status == 200) { // 如果ets侧正确设置路径列表,则此处能正常获取资源 const element = document.getElementById('text'); element.textContent = "load " + file + " success"; } else { // 如果ets侧不设置路径列表,则此处会触发CORS跨域检查错误 const element = document.getElementById('text'); element.textContent = "load " + file + " failed"; } } } xmlHttpReq.open("GET", file); xmlHttpReq.send(null); } </script></head>
<body><div class="page"> <button id="example" onclick="getFile()">stealFile</button></div><div id="text"></div></body>
</html>
复制代码


// main/resources/rawfile/js/script.jsconst body = document.body;const element = document.createElement('div');element.textContent = 'success';body.appendChild(element);
复制代码

5、HarmonyOS 有没有不随系统深色模式变化的操作?

应用主动设置深浅色模式,可参考官方文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-light-dark-color-adaptation-V5

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

轻口味

关注

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

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

评论

发布
暂无评论
【每日学点HarmonyOS Next知识】网页获取高度、行为菜单底部布局、动画问题、Web跨域加载图片、不随系统深色变化_HarmonyOS_轻口味_InfoQ写作社区