メインコンテンツまでスキップ

Cursor での Flutter 開発:完全ガイド

Cursor での Flutter 開発

Flutter は、開発者が単一のコードベースからモバイル、Web、デスクトップ用のネイティブコンパイルアプリケーションを構築できるようにします。Cursor の AI ネイティブな編集体験と組み合わせることで、Flutter 開発はさらに直感的になります。このガイドでは、Cursor での Dart プログラミング、ホットリロードの活用、効率的なウィジェット構築、および AI を使用したユーザーインターフェースの生成と改良をカバーします。


Cursor での Flutter セットアップ​

適切に設定された Flutter 環境は、すべてのターゲットプラットフォームでのスムーズな開発を保証します。Cursor は VS Code の Flutter および Dart 拡張機能を継承し、使い慣れたが強化されたワークフローを提供します。

Flutter と Dart SDK のインストール​

Cursor のターミナルでインストールを確認します:

flutter doctor

このコマンドは、Flutter SDK、Android ツールチェーン、macOS 上の Xcode、および接続されたデバイスをチェックします。進む前に報告された問題に対処してください。

ヒント

パスや権限の問題が発生した場合は、flutter doctor -v を実行して詳細な出力を取得してください。Cursor のターミナルはシェル環境を保持するため、PATH 設定はすぐに適用されます。

Cursor での拡張機能のインストール​

Cursor のマーケットプレイスから以下の拡張機能をインストールします:

  • Flutter:デバイス選択、エミュレータ起動、プロジェクト足場を含む完全な Flutter サポート
  • Dart:IntelliSense、リファクタリング、Flutter 固有のアシストを備えた Dart 言語サポート

これらの拡張機能により、コードスニペット、ウィジェットラッピングアシスト、および自動インポートが有効になります。

警告

Dart/Flutter 拡張機能セットが一つだけアクティブであることを確認してください。競合する拡張機能は、重複した診断や壊れたコード補完を引き起こす可能性があります。

プロジェクトの初期化と構造​

Cursor のターミナルから新しい Flutter プロジェクトを作成します:

flutter create my_app
cd my_app

標準的な Flutter プロジェクトには以下が含まれます:

my_app/
android/
ios/
lib/
main.dart
test/
pubspec.yaml

lib/ ディレクトリに Dart コードが配置され、pubspec.yaml が依存関係とアセットを管理します。


Cursor での Dart プログラミング​

Dart は Flutter を動かす言語です。Cursor の AI 機能は、最小限のボイラープレートでクリーンで型安全な Dart コードを書くのに役立ちます。

AI を活用した Dart コード生成​

ウィジェットや関数を自然言語で記述すると、Cursor は慣用的な Dart を生成します:

// タイトル、サブタイトル、末尾アイコンを表示する再利用可能なカードウィジェット

Cursor が生成:

import 'package:flutter/material.dart';

class InfoCard extends StatelessWidget {
final String title;
final String subtitle;
final IconData icon;
final VoidCallback? onTap;

const InfoCard({
super.key,
required this.title,
required this.subtitle,
required this.icon,
this.onTap,
});

@override
Widget build(BuildContext context) {
return Card(
elevation: 2,
child: ListTile(
leading: Icon(icon, color: Theme.of(context).primaryColor),
title: Text(title, style: Theme.of(context).textTheme.titleMedium),
subtitle: Text(subtitle),
trailing: const Icon(Icons.chevron_right),
onTap: onTap,
),
);
}
}
ヒント

すべてのウィジェットコンストラクタで super.key を使用してください。Cursor の Dart スニペットにはこれがデフォルトで含まれており、ウィジェットが最新の Flutter 規約に従うことを保証します。

Null 安全性と型推論​

Dart の null 安全性は、実行時の null 参照エラーを防ぎます。Cursor は nullable 型と non-nullable 型をハイライト表示します:

String? userName; // Nullable
late String displayName; // Non-nullable、後で初期化
final String id = 'abc'; // Non-nullable、不変

レガシーコードを移行する際は、Cursor の AI チャットに尋ねてください:

この関数を null 安全性と適切な型注釈を使用するように変換

非同期パターンと Streams​

Flutter は非同期プログラミングに大きく依存しています。Cursor は async/await パターンと Stream ビルダーを生成します:

Future<List<Product>> fetchProducts() async {
final response = await http.get(Uri.parse('/api/products'));
if (response.statusCode == 200) {
final List<dynamic> data = jsonDecode(response.body);
return data.map((json) => Product.fromJson(json)).toList();
}
throw Exception('Failed to load products');
}

ストリームを使用したリアクティブな UI 更新の場合:

StreamBuilder<List<Order>>(
stream: orderRepository.watchOrders(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
return ErrorWidget(snapshot.error!);
}
return OrderList(orders: snapshot.data ?? []);
},
)

ウィジェット構築と UI コンポジション​

Flutter のウィジェットツリーは強力ですが、冗長になることがあります。Cursor のアシストと AI 生成は、ウィジェット構築を効率化します。

ホットリロードと反復開発​

ホットリロードは Flutter のキラー機能です。Cursor では、flutter run を実行しているターミナルで r を押すと、コードの変更が即座に反映されます。これはほとんどの UI 変更、メソッド本体、およびウィジェットプロパティで機能します。

警告

ホットリロードはアプリの状態を保持します。main()、グローバル変数、または静的フィールドの変更には、ホットリスタート(R)を使用してください。

ウィジェットのラッピングとリファクタリング​

Cursor の Flutter 拡張機能は、一般的なウィジェット操作のためのクイックフィックスを提供します。ウィジェット上にカーソルを置き、電球メニューを使用して:

  • Wrap with Container
  • Wrap with Center
  • Wrap with Padding
  • Extract Widget
  • Remove Widget

これらのアシストにより、ウィジェットツリーを手動のカットアンドペーストなしで読みやすく保つことができます。

AI を使用した複雑なレイアウトの構築​

プレーンな英語でレイアウトを記述し、Cursor にウィジェットツリーを生成させます:

上部中央に円形のアバター、
次にユーザーの名前と自己紹介、次に写真のサムネイルグリッド、
そしてプロフィールを編集するためのフローティングアクションボタンがあるプロフィール画面

Cursor が組み立てます:

class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Column(
children: [
const SizedBox(height: 40),
CircleAvatar(
radius: 60,
backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
),
const SizedBox(height: 16),
Text(
'Jane Doe',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Text(
'Mobile developer and open source enthusiast.',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium,
),
),
const SizedBox(height: 24),
],
),
),
SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
delegate: SliverChildBuilderDelegate(
(context, index) => ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
'https://example.com/photo_$index.jpg',
fit: BoxFit.cover,
),
),
childCount: 12,
),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(context, '/edit-profile'),
child: const Icon(Icons.edit),
),
);
}
}

レスポンシブおよびアダプティブデザイン​

異なる画面サイズに適応するレイアウトを構築します:

class ResponsiveLayout extends StatelessWidget {
const ResponsiveLayout({super.key});

@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;

if (width > 1200) {
return const DesktopLayout();
} else if (width > 600) {
return const TabletLayout();
}
return const MobileLayout();
}
}
ヒント

フルスクリーンではなく特定の親ウィジェットの制約に応答する必要がある場合は、MediaQuery の代わりに LayoutBuilder を使用することを検討してください。


状態管理​

状態管理は Flutter で重要です。Cursor は、シンプルな setState から Riverpod や Bloc などの高度なソリューションまで、パターンの実装を支援します。

AI 生成の状態管理ボイラープレート​

Cursor に Riverpod プロバイダーの足場を組ませます:

import 'package:flutter_riverpod/flutter_riverpod.dart';

final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
return AuthNotifier(ref.read(authRepositoryProvider));
});

class AuthState {
final User? user;
final bool isLoading;
final String? error;

const AuthState({this.user, this.isLoading = false, this.error});

AuthState copyWith({User? user, bool? isLoading, String? error}) {
return AuthState(
user: user ?? this.user,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
}

class AuthNotifier extends StateNotifier<AuthState> {
final AuthRepository _repository;

AuthNotifier(this._repository) : super(const AuthState());

Future<void> signIn(String email, String password) async {
state = state.copyWith(isLoading: true, error: null);
try {
final user = await _repository.signIn(email, password);
state = state.copyWith(user: user, isLoading: false);
} catch (e) {
state = state.copyWith(error: e.toString(), isLoading: false);
}
}
}

UI との統合​

ウィジェットでプロバイダーを使用します:

class LoginScreen extends ConsumerWidget {
const LoginScreen({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final authState = ref.watch(authProvider);

return Scaffold(
body: authState.isLoading
? const Center(child: CircularProgressIndicator())
: LoginForm(
onSubmit: (email, password) {
ref.read(authProvider.notifier).signIn(email, password);
},
error: authState.error,
),
);
}
}
警告

レンダリングに影響する状態について、build メソッド内で ref.read を呼び出さないでください。ウィジェットが状態変化時に再構築されるように、ref.watch を使用してください。


AI 駆動の UI 生成​

Cursor の AI は、コード補完を超えて、記述からスクリーン全体、テーマ、およびアニメーションを生成します。

記述からのスクリーン生成​

スクリーンを記述し、Cursor に完全な実装を生成させます:

アカウント、通知、外観のセクションがある設定画面。
各セクションにはトグルスイッチとナビゲーション行があります。
Material 3 デザインのライトテーマを使用。

Cursor は、SwitchListTile、ListTile ナビゲーション、および適切なセクション区切りを備えた完全に構造化されたスクリーンを生成します。

テーマとカラースキームの生成​

完全な ThemeData 構成を生成します:

final appTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6750A4),
brightness: Brightness.light,
),
textTheme: const TextTheme(
headlineLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
bodyLarge: TextStyle(fontSize: 16, height: 1.5),
),
cardTheme: CardTheme(
elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
);

アニメーションとモーション​

Cursor は、AnimatedContainer、Hero、および明示的なアニメーションコントローラーを使用してアニメーションの足場を組むことができます:

class AnimatedButton extends StatefulWidget {
const AnimatedButton({super.key});

@override
State<AnimatedButton> createState() => _AnimatedButtonState();
}

class _AnimatedButtonState extends State<AnimatedButton>
with SingleTickerProviderStateMixin {
late AnimationController _controller;

@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
}

@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (_) => _controller.forward(),
onTapUp: (_) => _controller.reverse(),
child: ScaleTransition(
scale: Tween<double>(begin: 1.0, end: 0.95).animate(_controller),
child: ElevatedButton(
onPressed: () {},
child: const Text('Press Me'),
),
),
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
ヒント

アニメーションコントローラー、ストリームサブスクリプション、およびテキスト編集コントローラーは、常に dispose() メソッドで破棄して、メモリリークを防ぎましょう。


Flutter アプリのテストとデバッグ​

高品質の Flutter アプリには包括的なテストが必要です。Cursor は、AI 支援テスト生成を備えたユニットテスト、ウィジェットテスト、および統合テストをサポートします。

ウィジェットテスト​

UI の動作を検証するウィジェットテストを生成します:

import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/main.dart';

void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());

expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);

await tester.tap(find.byIcon(Icons.add));
await tester.pump();

expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}

レイアウト問題のデバッグ​

Cursor 内で Flutter の組み込みデバッグツールを使用します:

  • Debug Paint:ターミナルで p を押して、パディング、マージン、アラインメントを可視化
  • Widget Inspector:Flutter 拡張機能から DevTools を起動してウィジェットツリーを探索
  • Performance Overlay:P を押してフレームレンダリング時間を確認
警告

Flutter でレイアウトのオーバーフローエラーは一般的です。黄色と黒のストライプエラーが表示された場合は、Widget Inspector を使用して制約付きコンテナを特定し、Expanded、Flexible、または SingleChildScrollView の使用を調整してください。


まとめ​

Cursor での Flutter 開発は、Dart ウィジェットの表現力と AI 駆動の生産性を組み合わせています。即時の UI 生成やホットリロード反復から、堅牢な状態管理やテストまで、Cursor はクロスプラットフォーム開発のあらゆる段階を加速します。AI チャットを迅速なプロトタイピングに使用し、ウィジェットアシストを使用してコードをクリーンに保ち、リリース前には常に実機でテストしてください。Flutter IDE としての Cursor を使用すれば、あらゆる画面向けの美しいアプリの構築が、より高速で楽しくなります。