今回から新しいアプリを作っていきます
まず新規プロジェクトを作成
以下のように新規プロジェクトをつくります
名前はなんでも大丈夫です
ルーレットアプリを作ろう
何つくるか10分考えた結果、ルーレットアプリを作ります
パッケージが何個かあった覚えがあったので。。
とりあえずパッケージを入れてみます
terminalから、
flutter pub add flutter_fortune_wheel
を実行します

できたら、pubspec.yamlにさっきのパッケージがあるか確認します

できたら次はコードをちょこちょこ書いていきます
コードは前のパートでやったTesting_appを参考にしました
完成図

ファイル構成

こないな感じです
コード
main.dart
土台となるコードです
ルーティング設定だけ書いています。
import 'package:flutter/material.dart';
import 'package:myapp1/screens/roulette.dart';
import 'package:myapp1/screens/home.dart';
import 'package:flutter_fortune_wheel/flutter_fortune_wheel.dart';
//flutter_fortune_wheel含めパッケージをインポートします
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: {
HomePage.routeName: (context) => const HomePage(),
RoulettePage.routeName: (context) => const RoulettePage(),
},
initialRoute: HomePage.routeName,
); //ルーティング設定です(testing_appを参考にしてます)
}
}
home.dart
ホーム画面です
import 'package:flutter/material.dart';
import 'package:myapp1/screens/roulette.dart';
class HomePage extends StatelessWidget {
static const routeName = '/';
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Testing Sample'),
),
body: Center(
child: ElevatedButton(
child: const Text('ルーレットを開始'),
onPressed: () {
Navigator.pushNamed(context, RoulettePage.routeName);
},
),
), //ただ真ん中にボタン作りました
);
}
}
ただボタンを置いただけのシンプル構造ですが、とりあえずこれでいいでしょう
roulette.dart
ルーレット画面です。
flutter_fortune_wheelのサンプルコードをとりあえず参考に作りました
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_fortune_wheel/flutter_fortune_wheel.dart';
class RoulettePage extends StatelessWidget {
static const routeName = '/roulette_page';
const RoulettePage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fortune Wheel Example',
home: RouletteApp(), //ここでルーレットを呼び出しています
);
}
}
//ここからルーレットアプリの内部です
class RouletteApp extends StatefulWidget {
@override
_ExamplePageState createState() => _ExamplePageState();
}
class _ExamplePageState extends State<RouletteApp> {
StreamController<int> selected = StreamController<int>();
//streamControllerを作ります 後述
@override
Widget build(BuildContext context) {
final items = <String>[
'Aさん',
'Bさん',
'Cさん',
'Dさん',
'Eさん',
'Fさん',
'Gさん',
'Hさん',
];
//ルーレットに入れるアイテムを定義しています。
return Scaffold(
appBar: AppBar(
title: const Text('ルーレット'),
),
//ここから見た目の記述ですね
body: GestureDetector(
onTap: () {
//タップすると以下が動作します
setState(() {
//setStateはウィジェットを再構築するものです
//何回でもクリックするとルーレットが回るようにしています
selected.add(
Fortune.randomInt(0, items.length),
);
});
},
child: Column(
children: [
Expanded(
child: FortuneWheel(
selected: selected.stream,
items: [
for (var it in items) FortuneItem(child: Text(it)),
],
),
),
],
),
),
);
}
}
streamという機能がこのコードに出てきましたが、
【Dart入門】Streamの使い方 – プログラミング道場
この解説が一番わかりやすそうです。
そして今回のキモはstatefulwidgetのライフサイクルです。
つまりルーレットが何回も回せるようにsetState()をタップするごとに呼び出したりする処理です。
【Flutter】StatefulWidgetのライフサイクル
この記事がハイパーわかりやすいです。
つまり今はこのページに遷移するだけでルーレットが勝手に回っていますが、ルーレットスタートボタンを設置してそれが押されたらルーレットが回るようにできたり、ルーレットを終了ボタンを設置して二度と回すことができなくしたりできます。
とりあえずサンプルコード軽くいじっただけなので、もっと機能をつけるのを次のパートでやってみたいと思います。

