flutter-add-widget-preview について
Flutter Widget Previewerでプレビューを追加、反復調整するためのスキルです。Flutter開発者向けに、アノテーション、サイズ制約、再利用可能な設定、IDEやコマンドラインでの確認手順を説明します。
主な機能
- 01対応するウィジェット対象への @Preview 適用
- 02プレビュー名、グループ、サイズの設定
- 03再利用可能な Preview と MultiPreview 型の作成
- 04IDEまたはコマンドラインでのライブプレビュー反復
- 05Webプレビュー環境の制約への対応
活用シーン
- 01アプリ全体のコンテキストなしでのウィジェット確認
- 02ウィジェットのライト・ダーク表示
- 03制約のないウィジェットへのプレビューサイズ指定
- 04複数ウィジェット間でのプレビュー設定再利用
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dhruvanbhalara/ skills --skill flutter-add-widget-previewインストール後、Claude Code で/flutter-add-widget-previewを入力して読み込まれたか確認します。
詳細
目次
プレビューのガイドライン
Flutter Widget Previewer を使用すると、アプリケーション全体のコンテキストから切り離して、ウィジェットをリアルタイムでレンダリングできます。
- 対象要素:
@Previewアノテーションを適用する対象は次のとおりです。Widgetを返すトップレベル関数- クラス内の
Widgetを返す静的メソッド - 必須引数のない公開ウィジェットコンストラクター/ファクトリー
- インポート: 常に
package:flutter/widget_previews.dartをインポートしてください。 - 複数の構成: 単一の対象に複数の
@Previewアノテーションを適用すると、複数のプレビューインスタンスを作成できます (たとえばライト/ダークモード)。 - 命名: 整理されたプレビューパネルにするには、
nameパラメーターとgroupパラメーターを使用します。 - サイズ指定: ウィジェットが制約を受けない場合は、
sizeパラメーターで明示的な制約を適用します (プレビューアは既定でビューポートの約半分を使用します)。
制限への対処
Widget Previewer は Web 環境 で動作します。次の制約に従ってください。
| 制限 | 影響 | 回避策 |
|---|---|---|
dart:io なし | ファイルシステムやソケットを利用不可 | 条件付きインポートを使用してモックする |
dart:ffi なし | ネイティブコードが実行されない | プレビューモードでネイティブ呼び出しをスタブ化する |
| アセットパス | dart:ui の fromAsset にはパッケージパスが必要 | packages/my_package/assets/... を使用する |
| コールバック | 公開かつ定数である必要がある | アノテーションのパラメーターでクロージャを使用しない |
| 制約のないウィジェット | 正しくレンダリングされない可能性がある | @Preview で size パラメーターを設定する |
IDE と CLI の統合
IDE (Android Studio、IntelliJ、Flutter 3.38+ の VS Code)
- IDE を起動します。Widget Previewer が自動的に起動します。
- サイドバーの 「Flutter Widget Preview」 タブを開きます。
- 左下の 「Filter previews by selected file」 を切り替えて、アクティブなファイル以外のプレビューを表示します。
コマンドライン
flutter widget-preview start
ライブプレビューを備えた Chrome 環境を開きます。
フィードバックループ
- ウィジェットのコードまたはプレビューの構成を変更します。
- Widget Previewer で自動更新を確認します。
- グローバル状態を変更した場合 → 右下のグローバルホットリスタートをクリックします。
- ローカルのウィジェット状態のみをリセットする必要がある場合 → プレビューカードの個別のホットリスタートをクリックします。
- IDE/CLI コンソールでエラーを確認する → 修正する → 繰り返します。
カスタムアノテーション
Preview の拡張
Preview クラスを拡張することで、再利用可能なプレビュー構成を作成できます。
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';
final class ThemedPreview extends Preview {
const ThemedPreview({super.name, super.group});
PreviewThemeData _themeBuilder() {
return PreviewThemeData(
materialLight: ThemeData.light(),
materialDark: ThemeData.dark(),
);
}
@override
Preview transform() {
final originalPreview = super.transform();
final builder = originalPreview.toBuilder()
..name = 'Themed - ${originalPreview.name}'
..theme = _themeBuilder;
return builder.toPreview();
}
}
@ThemedPreview(name: 'Primary Button')
Widget primaryButton() => const ElevatedButton(onPressed: null, child: Text('Click'));
明るさバリアント向けの MultiPreview
final class MultiBrightnessPreview extends MultiPreview {
const MultiBrightnessPreview({required this.name});
final String name;
@override
List<Preview> get previews => const [
Preview(brightness: Brightness.light),
Preview(brightness: Brightness.dark),
];
@override
List<Preview> transform() {
return super.transform().map((preview) {
final builder = preview.toBuilder()
..group = 'Brightness'
..name = '$name - ${preview.brightness!.name}';
return builder.toPreview();
}).toList();
}
}
@MultiBrightnessPreview(name: 'User Card')
Widget userCard() => const Card(
child: Padding(padding: EdgeInsets.all(16), child: Text('John Doe')),
);
ワークフロー: ウィジェットプレビューの追加
タスクの進捗
- ステップ 1:
package:flutter/widget_previews.dartをインポートします。 - ステップ 2: 有効な対象 (トップレベル関数、静的メソッド、または引数なしのコンストラクター) を特定します。
- ステップ 3:
name、group、sizeパラメーターを指定して@Previewアノテーションを適用します。 - ステップ 4: 構成を複数のウィジェットで再利用する場合 → カスタムの
Previewサブクラスに抽出します。 - ステップ 5: プレビューアを起動します (IDE タブまたは
flutter widget-preview start)。 - ステップ 6: 繰り返します: ウィジェットを変更する → 自動更新を確認する → エラーを修正する → 繰り返します。
例
基本的なプレビュー
import 'package:flutter/widget_previews.dart';
import 'package:flutter/material.dart';
@Preview(name: 'Greeting Text', group: 'Typography')
Widget greetingText() {
return const Text('Hello, World!', style: TextStyle(fontSize: 24));
}
サイズ制約付きのプレビュー
@Preview(
name: 'Login Form',
group: 'Forms',
size: Size(400, 600),
)
Widget loginFormPreview() {
return const MaterialApp(home: LoginForm());
}
コンストラクターでのプレビュー
@Preview(name: 'Default Avatar')
class UserAvatar extends StatelessWidget {
const UserAvatar({super.key});
@override
Widget build(BuildContext context) {
return const CircleAvatar(radius: 40, child: Icon(Icons.person));
}
}
コメント
Markdown 対応