[Daily HarmonyOS Next Knowledge] Web Page Height Acquisition, Action Menu Bottom Layout, Animation Issues, Web Cross-Origin Image Loading, System Dark Mode Immunity
1. HarmonyOS: Discrepancy between getPageHeight() and actual web page height in Web control?
Calling getWebViewController().getPageHeight()
in the Web's onPageEnd()
method returns a height smaller than the actual web content height. Using setTimeout(() => { let webHeight1 = this.controller.getWebViewController().getPageHeight(); Logger.getInstance().error('Internal control height time', ' webHeight:' + webHeight1 + ' webHeight:' + vp2px(webHeight1)); }, 200)
obtains the correct height. Is there a way to get the actual height without delay?
onPageEnd
is a callback when page loading completes, not when page rendering finishes, hence the height discrepancy. Use onFirstMeaningfulPaint
:
Documentation: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-web-V5#ZH-CN_TOPIC_0000001847049744__onfirstmeaningfulpaint12
2. Does HarmonyOS promptAction.showActionMenu support bottom layout?
Does the promptAction.showActionMenu
interface support pop-up layout at the bottom? The documentation does not mention alignment settings, and examples show centered layouts.
Reference 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
@Component
struct 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. Must HarmonyOS animations be paired with @State-decorated variables to take effect?
Generally, animations require @State
-decorated variables. The following demo works with Text().width(300).height(300).backgroundColor(Color.Black)
:
@Entry
@Component
export default struct ParticleStar {
aboutToAppear(): void {
}
build() {
Stack() {
Text()
.width(300).height(300).backgroundColor(Color.Black);
Particle({
particles: [
{
emitter: {
particle: {
type: ParticleType.POINT, // Particle type
config: {
radius: 10 // Dot radius
},
count: 500, // Total particles
lifetime: 10000 // Particle lifetime in ms
},
emitRate: 10, // Particles emitted per second
position: [200, 0],
shape: ParticleEmitterShape.RECTANGLE // Emitter shape
},
color: {
range: [Color.Red, Color.Yellow], // Initial color range
updater: {
type: ParticleUpdater.CURVE, // Change mode: curve
config: [
{
from: Color.White, // Start value
to: Color.Pink, // End value
startMillis: 0, // Start time
endMillis: 3000, // End time
curve: Curve.EaseIn // Change curve
},
{
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], // Initial opacity range [0.0 to 1.0]
updater: {
type: ParticleUpdater.CURVE, // Opacity change mode: 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: {
// Acceleration configuration: magnitude and direction
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 component cannot load cross-origin image resources?
When an app accesses a web page, some images fail to load due to cross-origin restrictions. How to resolve this?
For cross-origin issues, refer to: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/web-cross-origin-V5
To enhance security, the ArkWeb kernel prohibits cross-origin requests from file or resource protocols. When loading local offline resources via the Web component, cross-origin access to file/resource protocols is blocked. Two solutions:
Method 1
Use http/https protocols instead of file/resource protocols. Intercept and replace local resources using the Web component's onInterceptRequest
method to avoid CORS blocking.
Method 2
Set an allowed path list via setPathAllowingUniversalAccess
to enable cross-origin access to local files via the file protocol. Path formats must comply with:
- Application file directory (via
Context.filesDir
):-
/data/storage/el2/base/files/example
-
/data/storage/el2/base/haps/entry/files/example
-
- Application resource directory (via
Context.resourceDir
):-
/data/storage/el1/bundle/entry/resource/resfile
-
/data/storage/el1/bundle/entry/resource/resfile/example
-
// main/ets/pages/Index.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct WebComponent {
controller: WebviewController = new webview.WebviewController();
build() {
Row() {
Web({ src: "", controller: this.controller })
.onControllerAttached(() => {
try {
// Set allowed cross-origin paths
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";
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) {
const element = document.getElementById('text');
element.textContent = "load " + file + " success";
} else {
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.js
const body = document.body;
const element = document.createElement('div');
element.textContent = 'success';
body.appendChild(element);
5. HarmonyOS: How to prevent adaptation to system dark mode?
To manually set light/dark mode, refer to the official document: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-light-dark-color-adaptation-V5
Top comments (0)