レイアウト設計の基礎と応用
ArkUIでは、画面構成は「コンポーネントの組み合わせ」として実現されます。適切なレイアウトを選択することで、視覚的にも操作的にも優れたインターフェースが構築可能です。
レイアウトの構造理解
- 青領域:要素の物理的なサイズ(
width/heightで設定)
- 黄領域:実際の描画可能範囲(青領域 - ボーダー値)
- 緑領域:コンテンツの本質的なサイズ(例:テキストの自動拡張)
- 破線領域:マージンを含む全体的な影響範囲
主要レイアウトコンポーネントの使い分け
| コンポーネント |
使用シーン |
サンプルコード |
Row / Column |
直列配置が必要な場合(複数要素) |
Row() { Text('商品1'); Text('商品2'); } |
Stack |
重ね合わせ(例:ボタン上にアイコン) |
Stack() { Image('star'); Button('いいね') } |
Flex |
比率に基づく自動調整 |
Flex({ direction: 'row' }) { Text('A').flexGrow(1); Text('B').flexGrow(2); } |
RelativeContainer |
複雑な2次元配置(ネスト回避) |
RelativeContainer() { Image().position({ x: 50, y: 30 }); Text('名前') } |
List |
スクロール可能な長リスト(チャット履歴など) |
List({ data: messages }) { Item(() => Text(item.text)) } |
位置制御の技法
// 絶対位置指定(親要素の左上を原点)
Component().position({ x: 40, y: 60 })
// 相対移動(自身の元位置からのずれ)
Component().offset({ x: 10, y: -5 })
子要素の制御戦略
| 効果 |
プロパティ |
例 |
| 拡張 |
flexGrow, flexShrink |
Text('伸縮').flexGrow(1) |
| アスペクト比維持 |
aspectRatio |
Image().aspectRatio(1.8) |
| 表示優先度 |
displayPriority |
Button().displayPriority(3) |
実用的なベストプラクティス
画像処理の高度な技術
Imageコンポーネントの活用法
PNG/JPG/SVG/GIF等をサポートし、多様な表示が可能。
// 基本的な画像表示
Image($r('app.media.logo'))
Image('https://example.com/banner.jpg')
Image('images/icon.png')
画像の読み込みモード
| 種別 |
用途 |
例 |
| リソース引用 |
共通画像の再利用 |
Image($r('app.media.icon')) |
| ネットワーク画像 |
動的コンテンツ |
Image('https://.../avatar.jpg') |
| メディアライブラリ |
ユーザー選択画像 |
Image('file://media/Photos/1') |
| Base64埋め込み |
小規模画像内蔵 |
Image('data:image/png;base64,...') |
矢量画像のカスタマイズ
// SVGの色変更
Image($r('app.media.sun'))
.fillColor(Color.Yellow)
.width(60)
画像のスタイル調整
objectFit:表示モード(Contain/Cover/Fill)
objectRepeat:パターン繰り返し(X/Y/XY)
colorFilter:フィルター効果(レトロ・モノクロなど)
パフォーマンス最適化
- 解像度制限:
.sourceSize({ width: 150, height: 150 })
- 補間品質:
.interpolation(ImageInterpolation.High)
- 同期読み込み:
.syncLoad(true)(注意:非同期が推奨)
イベントハンドリング
Image('banner.jpg')
.onComplete((msg) => {
console.log(`画像サイズ: ${msg.width}x${msg.height}`);
})
.onError(() => {
console.log('画像読込失敗');
})
テキスト表示とインタラクション
TextとSpanの使い分け
Text:独立した段落やタイトル
Span:Text内での部分的スタイル適用
Text('これは') {
Span('赤文字').decoration({
type: TextDecorationType.LineThrough,
color: Color.Red
})
Span('青下線').decoration({
type: TextDecorationType.Underline,
color: Color.Blue
})
}
テキストスタイルのカスタム
textAlign:左・中央・右揃え
maxLines/textOverflow:省略表示(Ellipsis/Marquee)
textCase:大文字/小文字変換
letterSpacing:字間調整
baselineOffset:基線位置変更
インタラクティブなテキスト
Text('クリック可能')
.onClick(() => {
console.log('タップされた');
})
Text() {
Span('リンク風').onClick(() => {
router.pushUrl({ url: 'pages/detail' });
})
}
アクセシビリティ対応
Text('重要通知')
.accessibilityDescription('システム更新に関する緊急情報です')
入力欄の完全マニュアル
TextInput vs TextArea
TextInput:単一行入力(ログインフォームなど)
TextArea:複数行入力(コメント欄など)
TextInput({ placeholder: 'メールアドレス' })
.type(InputType.Email)
TextArea({ text: '詳細説明...' }).maxLength(500)
入力タイプの選択
| タイプ |
用途 |
例 |
Password |
パスワード入力(マスク表示) |
.type(InputType.Password) |
Number |
数字専用キーボード |
.type(InputType.Number) |
PhoneNumber |
電話番号入力 |
.type(InputType.PhoneNumber) |
キーボード遮蔽対策
Scroll() {
Column() {
ForEach(messages, (msg) => {
TextArea({ text: msg.content })
.margin(10)
})
}
}
ボタンのデザインとインタラクション
ボタンの種類
ButtonType.Capsule:カプセル型(丸み固定)
ButtonType.Circle:完全な円形
ButtonType.Normal:自由な角丸設定
スタイルのカスタマイズ
// 渐变背景
Button('VIP特典')
.linearGradient({
angle: 45,
colors: [[0xff00ff, 0], [0x00ffff, 1]]
})
// シャドウ付き
Button('新着')
.shadow({ radius: 8, color: Color.Gray })
クリックイベントと安全対策
let isSubmitting = false;
Button('送信')
.onClick(() => {
if (isSubmitting) return;
isSubmitting = true;
// API呼び出し
setTimeout(() => { isSubmitting = false; }, 1500);
})
特殊な使い方
- 長押しによるコピーアクション:
.onLongPress(() => clipboard.copy(...))
- 振動フィードバック:
.onTouch(event => if (event.type === TouchType.Down) vibrator.vibrate(30))
- ロード中状態:
Button({ type: ButtonType.Normal }) { LoadingProgress().width(20); Text('処理中...') }