見出し画像

Flutterでルーレット画面を作る

初めましてblueです。

現在、ITベンチャー企業でWEBキャンペーンシステムの開発並びに要件定義を行なっています。

今回はFlutterでルーレット画面を作る方法について記事にしてみました!

使用するパッケージ

※最近(2021/12/19)出来たパッケージなので、今後封鎖する可能性もあります。

実装コード

RouletteController(
    group: RouletteGroup([
      const RouletteUnit.noText(color: Colors.red),
      const RouletteUnit.noText(color: Colors.green),
      const RouletteUnit.noText(color: Colors.blue),
      const RouletteUnit.noText(color: Colors.yellow),
    ]),
    vsync: this 
  );

RouletteControllerのインスタンスを作成。
RouletteGroupの中に表示させたい項目を入れます。

RouletteUnit.noText:テキストなしのセクターを作成
RouletteUnit.text:テキストありのセクターを作成

Roulette(
 controller: _controller,
 style: const RouletteStyle(
   dividerThickness: 4,
 ),
),

RouletteControllerを作成することでRouletteが使用できます
表示させたい場所にRouletteで囲む。

RouletteStyle:レンダリングスタイルを設定
dividerThickness:パーツごとの仕切りの厚さを設定

_controller.rollTo(
   2,
   clockwise: _clockwise,
   offset: Random().nextDouble(),
 ),

rollTo:ルーレットを回す時間を決めて、アニメーションを実行
ランダムで止まるように設定。

全体コード(※サンプルコード参照しつつ、一部修正)

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

import 'package:roulette/roulette.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Roulette',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late RouletteController _controller;
  bool _clockwise = true;

  @override
  void initState() {
    _controller = RouletteController(
    group: RouletteGroup([
      const RouletteUnit.noText(color: Colors.red),
      const RouletteUnit.noText(color: Colors.green),
      const RouletteUnit.noText(color: Colors.blue),
      const RouletteUnit.noText(color: Colors.yellow),
    ]),
    vsync: this 
  );

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ルーレット'),
      ),
      body:Container(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Text(
                    "右回り",
                    style: TextStyle(fontSize: 18),
                  ),
                  Switch(
                    value: _clockwise,
                    onChanged: (onChanged) {
                      setState(() {
                        _controller.resetAnimation();
                        _clockwise = !_clockwise;
                      });
                    },
                  ),
                ],
              ),
              Stack(
                alignment: Alignment.topCenter,
                children: [
                  SizedBox(
                    width: 260,
                    height: 260,
                    child: Padding(
                      padding: const EdgeInsets.only(top: 30),
                      child: Roulette(
                        controller: _controller,
                        style: const RouletteStyle(
                          dividerThickness: 4,
                        ),
                      ),
                    ),
                  ),
                  const Icon(
                    FontAwesomeIcons.longArrowAltDown,
                    size: 45,
                    color: Colors.grey,
                    ),
                ],
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _controller.rollTo(
          2,
          clockwise: _clockwise,
          offset: Random().nextDouble(),
        ),
        child: const Icon(Icons.refresh_rounded),
      ),
    );
  }

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

実装画面

この記事が参加している募集

最近の学び

良かったらサポートしていただけると嬉しいです!