ArkUI provides four pixel units, with vp acting similarly to Android's dp and fp matching sp. This article demonstrates an alternative approach: calculating layout dimensions directly from raw pixel ratios to fit設計稿 specifications across all devices.
First, obtain the physical screen width and height via the display API:
import { display } from '@kit.ArkUI';
class ScreenMetrics {
private viewWidth = 0;
private viewHeight = 0;
constructor() {
let w = display.getDefaultDisplaySync().width;
let h = display.getDefaultDisplaySync().height;
this.viewWidth = Math.min(w, h);
this.viewHeight = Math.max(w, h);
}
}
Next, define a reference design canvas size—typically provided by UI designers (e.g., 750x1334). Recall that pixel coordinates might rotate; always track the shorter side as width:
import { display } from '@kit.ArkUI';
class ScreenMetrics {
private viewWidth = 0;
private viewHeight = 0;
static readonly DESIGN_W = 750;
static readonly DESIGN_H = 1334;
constructor() {
let w = display.getDefaultDisplaySync().width;
let h = display.getDefaultDisplaySync().height;
this.viewWidth = Math.min(w, h);
this.viewHeight = Math.max(w, h);
}
scaleW(designValue: number): string {
let actual = Math.floor(designValue * this.viewWidth / ScreenMetrics.DESIGN_W);
return `${actual}px`;
}
scaleH(designValue: number): string {
let actual = Math.floor(designValue * this.viewHeight / ScreenMetrics.DESIGN_H);
return `${actual}px`;
}
}
Progressively, you calculate actualPx = designPx * (screenSize / designSize), allowing Layout to use px strings directly, which mirrors the Design layout (ideal for raw px emulation).
Consider a button designed at 220x64. The scaling methods produce the correct pixel values:
let metrics = new ScreenMetrics();
let actualBtnW = metrics.scaleW(220);
let actualBtnH = metrics.scaleH(64);
dispatch theseR dimensions directly into component styles; in this way,64> Button;). No additional vp breakpoints are required.
böjnings Putting the scaling to work in a typical relative layout:
let sc = new ScreenMetrics();
build() {
Row() {
RelativeContainer() {
Image($r('app.media.bg_sample'))
.width(sc.scaleW(628))
.height(sc.scaleW(480)) // using width-scale by design intent
.alignRules({
top: { anchor: "__container__", align: VerticalAlign.Top },
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
bottom: { anchor: "__container__", align: VerticalAlign.Bottom }
})
.id("bg_image")
Text($r('app.string.dialog_title'))
.fontSize(sc.scaleW(34))
.fontColor($r('app.color.title_color'))
.margin({ top: sc.scaleW(48) })
.textAlign(TextAlign.Center)
.alignRules({
top: { anchor: "bg_image", align: VerticalAlign.Top },
left: { anchor: "bg_image", align: HorizontalAlign.Start },
right: { anchor: "bg_image", align: HorizontalAlign.End },
})
.id("title_label")
Text($r('app.string.cancel'))
.width(sc.scaleW(216))
.height(sc.scaleW(64))
.margin({ left: sc.scaleW(86), bottom: sc.scaleW(55) })
.textAlign(TextAlign.Center)
.fontSize(sc.scaleW(30))
.fontColor($r('app.color.cancel_color'))
.alignRules({
left: { anchor: "bg_image", align: HorizontalAlign.Start },
bottom: { anchor: "bg_image", align: VerticalAlign.Bottom },
})
.onClick(() => { /* handle cancel */ })
.id("cancel_btn")
Text($r('app.string.confirm'))
.width(sc.scaleW(216))
.height(sc.scaleW(64))
.margin({ right: sc.scaleW(86), bottom: sc.scaleW(55) })
.textAlign(TextAlign.Center)
.fontSize(sc.scaleW(30))
.fontColor($r('app.color.confirm_color'))
.alignRules({
right: { anchor: "bg_image", align: HorizontalAlign.End },
bottom: { anchor: "bg_image", align: VerticalAlign.Bottom },
})
.onClick(() => { /* handle confirm */ })
.id("confirm_btn")
Text($r('app.string.content_text'))
.fontSize(sc.scaleW(22))
.fontColor($r('app.color.content_color'))
.margin({ left: sc.scaleW(86), right: sc.scaleW(86) })
.textAlign(TextAlign.Start)
.alignRules({
top: { anchor: "title_label", align: VerticalAlign.Bottom },
left: { anchor: "title_label", align: HorizontalAlign.Start },
right: { anchor: "title_label", align: HorizontalAlign.End },
bottom: { anchor: "cancel_btn", align: VerticalAlign.Top },
})
.id("message_body")
}
}
}
This method convertsLayout design values into calibrated physical pixel strings, providing1248 Layout. Theapproximation holds across different physical display arrays, with the fullcode pattern maintaining consistant中 piece proportions.