HarmonyOS の ArkUI では、mediaquery モジュールを用いてデバイスの状態(例:画面向き、解像度など)に応じて UI を動的に変更できます。以下は、横画面(landscape)かどうかを監視し、状態変化時にコールバックを実行する基本的な実装です。
import mediaquery from '@ohos.mediaquery';
// 横画面条件でメディアクエリを同期的に生成
const mediaListener = mediaquery.matchMediaSync('(orientation: landscape)');
// 状態変化時のハンドラ
function handleOrientationChange(result: mediaquery.MediaQueryResult): void {
if (result.matches) {
// 横画面時の処理
} else {
// 縦画面時の処理
}
}
// 'change' イベントにハンドラを登録
mediaListener.on('change', handleOrientationChange);
メディアクエリの構文と機能
メディアクエリは以下の形式で記述されます:
[メディアタイプ] [論理演算子] [(メディア特性)]
例:screen and (device-type: tablet) or (resolution >= 2)
これは「画面デバイスであり、かつタブレットであるか、または解像度が2以上」の場合にマッチします。
メディアタイプ
| タイプ | 説明 |
|---|---|
screen | 画面デバイス(スマホ、タブレット、PCなど)に適用 |
論理演算子
| 演算子 | 意味 |
|---|---|
and | すべての条件を満たす |
or | いずれかの条件を満たす |
not | 条件を否定 |
only | 特定のメディアタイプに限定 |
,(カンマ) | 複数のクエリをグループ化 |
比較演算子
メディア特性の範囲指定には以下の演算子が使用可能:
<:未満>:超過<=:以下>=:以上
主なメディア特性
| 特性名 | 説明 |
|---|---|
width, height | 描画領域の幅・高さ(px) |
min-width, max-width | 最小・最大幅 |
min-height, max-height | 最小・最大高さ |
resolution | 解像度(dpi, dppx, dpcm 対応) |
orientation | portrait(縦)または landscape(横) |
device-type | default(スマホ)または tablet |
round-screen | 円形画面かどうか(boolean) |
dark-mode | ダークモード有効時 true |
実装例(Stageモデル)
import mediaquery from '@ohos.mediaquery';
import window from '@ohos.window';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct ResponsiveLayout {
@State textColor: string = '#DB7093';
@State label: string = 'Portrait';
private orientationListener = mediaquery.matchMediaSync('(orientation: landscape)');
onOrientationChange(result: mediaquery.MediaQueryResult): void {
if (result.matches) {
this.textColor = '#FFD700';
this.label = 'Landscape';
} else {
this.textColor = '#DB7093';
this.label = 'Portrait';
}
}
aboutToAppear(): void {
const boundHandler = this.onOrientationChange.bind(this);
this.orientationListener.on('change', boundHandler);
}
switchOrientation(toLandscape: boolean): void {
const ctx = getContext(this) as common.UIAbilityContext;
window.getLastWindow(ctx).then(win => {
win.setPreferredOrientation(
toLandscape ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT
);
});
}
build(): void {
Column({ space: 50 }) {
Text(this.label)
.fontSize(50)
.fontColor(this.textColor)
Text('Landscape Mode')
.fontSize(40)
.backgroundColor('#FFA500')
.onClick(() => this.switchOrientation(true))
Text('Portrait Mode')
.fontSize(40)
.backgroundColor('#FFA500')
.onClick(() => this.switchOrientation(false))
}
.width('100%')
.height('100%');
}
}