Open In App

Flutter – Create Fortune Wheel Spin

Last Updated : 06 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Deciding what to eat can be a daily dilemma, especially when you have a plethora of options to choose from. To make this decision-making process more exciting and interactive, in this article, we will be creating – the Lunch Spinning Wheel app. A sample video is given below to get an idea about what we are going to do in this article.

Prerequisites

Before we dive into the implementation, make sure Flutter is installed on the system or download it from the official Flutter website. Also, ensure that a code editor is installed, such as Visual Studio Code or Android Studio.

Step-by-Step Implementation

Step 1: Create Project

In the Visual Studio Code terminal run the below command to create a Flutter project:

Dart




flutter create lunch_spinning_wheel


Step 2: Add libraries

Now we need to add the package into the pubspec.yaml file. From the command line:

Dart




flutter pub add flutter_fortune_wheel http confetti


This will add all packages under dependencies section in pubspec.yaml file as shown below:

yaml2

Step 3: Import libraries

Now, import these packages in main.dart file,

Dart




import 'package:http/http.dart' as http;
import 'package:flutter_fortune_wheel/flutter_fortune_wheel.dart';
import 'package:confetti/confetti.dart';


Step 4: Create Lunch Class

Create Lunch class that requires the meal parameter to be provided when creating an instance of the Lunch class and the img parameter is optional. The fromJson factory method is used to create Lunch instances by extracting values from a JSON map.

Dart




class Lunch {
  final String meal;
  var img;
  
  Lunch({required this.meal, this.img});
  
  factory Lunch.fromJson(Map<String, dynamic> json) {
    return Lunch(meal: json['strMeal'], img: json['strMealThumb']);
  }
}


Step 5: Loading Lunch Ideas from an API

Fetch a list of lunch ideas from the MealDB API to retrieve a variety of Indian meal options.

Dart




 List<Lunch> _ideas = [];
 
 Future<void> _getLunchIdeas() async {
   http.Response response;
 
   Uri uri = Uri.parse(url);
   response = await http.get(uri);
 
   if (response.statusCode == 200) {
     Map<String, dynamic> jsonData = json.decode(response.body);
 
     if (jsonData['meals'] != null) {
       List<dynamic> meals = jsonData['meals'];
       setState(() {
         _ideas = meals.map((json) => Lunch.fromJson(json)).toList();
       });
     }
   }
 }


Step 6: Create the Spinning Wheel

The spinning wheel is implemented using the FortuneWheel widget provided by the Flutter Fortune Wheel package. It takes the list of lunch ideas and randomly selects one when the wheel is spun. The selected idea is displayed in alert dialog when wheel is stopped.

Dart




FortuneWheel(
             selected: selected.stream,
             items: [
                    for (var it in _ideas)
                              FortuneItem(child: Text(it.meal)),
                          ],
                          onAnimationEnd: () {
                            _centerController.play();
                            showDialog(
                                barrierDismissible: true,
                                context: context,
                                builder: (BuildContext context) {
                                  return Center(
                                    child: AlertDialog(
                                      scrollable: true,
                                      title: Text("Hurray! today's meal is????"),
                                      content: Column(
                                        children: [
                                          ConfettiWidget(
                                              confettiController:
                                                  _centerController,
                                              blastDirection: pi / 2,
                                              maxBlastForce: 5,
                                              minBlastForce: 1,
                                              emissionFrequency: 0.03,
                                              numberOfParticles: 10,
                                              gravity: 0),
                                          SizedBox(height: 10),
                                          Text(
                                            selectedIdea,
                                            style: TextStyle(fontSize: 22),
                                          ),
                                          SizedBox(height: 20),
                                          Image.network(selectedImg),
                                        ],
                                      ),
                                    ),
                                  );
                                });
                          },
                          onFocusItemChanged: (value) {
                            if (flag == true) {
                              setValue(value);
                            } else {
                              flag = true;
                            }
                          },
                        ),


Complete Code

Dart




import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:flutter_fortune_wheel/flutter_fortune_wheel.dart';
import 'package:confetti/confetti.dart';
  
void main() => runApp(const MyApp());
  
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Gfg Lunch Wheel',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: ExamplePage(),
    );
  }
}
  
class ExamplePage extends StatefulWidget {
  @override
  _ExamplePageState createState() => _ExamplePageState();
}
  
class Lunch {
  final String meal;
  var img;
  
  Lunch({required this.meal, this.img});
  
  factory Lunch.fromJson(Map<String, dynamic> json) {
    return Lunch(meal: json['strMeal'], img: json['strMealThumb']);
  }
}
  
class _ExamplePageState extends State<ExamplePage> {
  StreamController<int> selected = StreamController<int>();
  late ConfettiController _centerController;
  
  List<Lunch> _ideas = [];
  
  Future<void> _getLunchIdeas() async {
    http.Response response;
  
    Uri uri = Uri.parse(url);
    response = await http.get(uri);
  
    if (response.statusCode == 200) {
      Map<String, dynamic> jsonData = json.decode(response.body);
  
      if (jsonData['meals'] != null) {
        List<dynamic> meals = jsonData['meals'];
        setState(() {
          _ideas = meals.map((json) => Lunch.fromJson(json)).toList();
        });
      }
    }
  }
  
  @override
  void initState() {
    super.initState();
    _getLunchIdeas();
    _centerController =
        ConfettiController(duration: const Duration(seconds: 10));
  }
  
  @override
  void dispose() {
    selected.close();
    _centerController.dispose();
    super.dispose();
  }
  
  var selectedIdea = "";
  late var selectedImg;
  void setValue(value) {
    selectedIdea = _ideas[value].meal.toString();
    selectedImg = _ideas[value].img;
  }
  
  @override
  Widget build(BuildContext context) {
    var flag = false;
  
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: const Text('Gfg Lunch Wheel'),
        ),
        body: _ideas.length > 2
            ? Padding(
                padding: const EdgeInsets.all(8.0),
                child: GestureDetector(
                  onTap: () {
                    setState(() {
                      selected.add(
                        Fortune.randomInt(0, _ideas.length),
                      );
                    });
                  },
                  child: Column(
                    children: [
                      Expanded(
                        child: FortuneWheel(
                          selected: selected.stream,
                          items: [
                            for (var it in _ideas)
                              FortuneItem(child: Text(it.meal)),
                          ],
                          onAnimationEnd: () {
                            _centerController.play();
                            showDialog(
                                barrierDismissible: true,
                                context: context,
                                builder: (BuildContext context) {
                                  return Center(
                                    child: AlertDialog(
                                      scrollable: true,
                                      title: Text("Hurray! today's meal is????"),
                                      content: Column(
                                        children: [
                                          ConfettiWidget(
                                              confettiController:
                                                  _centerController,
                                              blastDirection: pi / 2,
                                              maxBlastForce: 5,
                                              minBlastForce: 1,
                                              emissionFrequency: 0.03,
                                              numberOfParticles: 10,
                                              gravity: 0),
                                          SizedBox(height: 10),
                                          Text(
                                            selectedIdea,
                                            style: TextStyle(fontSize: 22),
                                          ),
                                          SizedBox(height: 20),
                                          Image.network(selectedImg),
                                        ],
                                      ),
                                    ),
                                  );
                                });
                          },
                          onFocusItemChanged: (value) {
                            if (flag == true) {
                              setValue(value);
                            } else {
                              flag = true;
                            }
                          },
                        ),
                      ),
                    ],
                  ),
                ),
              )
            : Center(
                child: CircularProgressIndicator(color: Colors.green),
              ));
  }
}


Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads