简体   繁体   中英

How to get radio button value to int and calculate in flutter

这是这个练习的输出 I just started to learn Flutter/Dart as my lecturer ask me to do some simple mobile app of e-ticket where the user need to choose from the radio button the movie that have value price for each radio button. Then the user need to input quantity value then click the submit button where the result of calculation need to be shown in another result page. Below is the picture of the assignment and some code that i have done. But i got stuck in the calculation part where i did not find any solution to this. hope anyone can help me with this.

main dart main dart

import 'package:flutter/material.dart';
import 'result.dart';
import 'customer.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
enum SingingCharacter { avengers, batman, kimetsu }

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  final txtName= TextEditingController();
  final txtEmail = TextEditingController();
  final txtQuantity = TextEditingController();
  SingingCharacter? _character = SingingCharacter.avengers;

  void _gotoResultScreen(){

    Customer c= Customer(txtName.text, txtEmail.text, int.parse(txtQuantity.text));

    Navigator.push(
      context,
      MaterialPageRoute(
          builder: (context) => ResultPage(
            title:"Result Screen",
            content:"Congratulation! You've reached this page",
            customer: c,)
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(

        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Name'),
            TextField(
              controller: txtName,
            ),
            Text('Email'),
            TextField(
              controller: txtEmail,
            ),

            Text('Choose a movie:'),
            ListTile(
              title: const Text('AVENGERS(RM20)'),
              leading: Radio<SingingCharacter>(
                value: SingingCharacter.avengers,
                groupValue: _character,
                onChanged: (SingingCharacter? value) {
                  setState(() {
                    _character = value;
                  });
                },
              ),
            ),
            ListTile(
              title: const Text('BATMAN(RM10)'),
              leading: Radio<SingingCharacter>(
                  value: SingingCharacter.batman,
                  groupValue: _character,
                  onChanged: (SingingCharacter? value) {
                    setState(() {
                      _character = value;
                    });
                  }
              ),
            ),

            ListTile(
              title: const Text('KIMETSU NO YAIBA(RM12)'),
              leading: Radio<SingingCharacter>(
                  value: SingingCharacter.kimetsu,
                  groupValue: _character,
                  onChanged: (SingingCharacter? value) {
                    setState(() {
                      _character = value;
                    });
                  }
              ),
            ),

            Text('quantity'),
            TextField(
              controller: txtQuantity,
            ),

            RaisedButton(
              onPressed:_gotoResultScreen,
              //do something
              child: new Text('Calculate'),
            ),
          ],
        ),
      ),
    );
  }
}

result.dart

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

class ResultPage extends StatefulWidget {
  const ResultPage({Key? key, required this.title, required this.content, required this.customer}) : super(key: key);

  final String title;
  final String content;
  final Customer customer;

  @override
  State<ResultPage> createState() => _ResultPageState();
}

class _ResultPageState extends State<ResultPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(widget.content,),
            Text("Name:" + widget.customer.name),
            Text("Email: " + widget.customer.email),
            Text("Quantity:" + widget.customer.quantity.toString()),
          ],
        ),
      ),
    );
  }
}

customer.dart

  class Customer {
  final String name;
  final String email;
  final int quantity;



  const Customer(this.name, this.email, this.quantity);
}

You can use Map<String, int> to store the movie name and its price. Then create the List<Map<String, int>> and use the .map() function on this list to covert the list into listTile .

You should pass necessary arguments to result page. You passed Customer, that is ok. But movie info is missing. For example:

Navigator.push(
  context,
  MaterialPageRoute(
      builder: (context) => ResultPage(
        title:"Result Screen",
        content:"Congratulation! You've reached this page",
        customer: c,
        movieName: ...,
        price: ...,
      )
  ),
);

And of course you should edit Result page accordingly.

After go to result page. Use price data and multiply quantity. This is gonna be final price.

However, this is not a good approach, Instead of using this kind of solutions, I recommend create a Movie class like Customer. Also quantity info should not be a field of Customer, it should be field of Movie class.

You can calculate the price like this.

Let's say your _character value is SingingCharacter.avengers

int price = getPriceFromCharacter(_character) * int.parse(txtQuantity.text);

getPriceFromCharacter(SingingCharacter? character) {
 switch(character) { 
   case SingingCharacter.avengers: { 
     return 20;
   } 
   case SingingCharacter.batman: { 
     return 10;
   } 
   case SingingCharacter.kimetsu: { 
     return 12;
   } 
  } 
}
void _gotoResultScreen(){
  int price = getPriceFromCharacter(_character) * int.parse(txtQuantity.text);
  Customer c= Customer(txtName.text, txtEmail.text, int.parse(txtQuantity.text));

  Navigator.push(
   context,
  MaterialPageRoute(
      builder: (context) => ResultPage(
        title:"Result Screen",
        content:"Congratulation! You've reached this page",
        customer: c,)
  ),
);

}

This is the answer to the solution above. main.dart

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

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'eTicket'),
    );
  }
}

enum ticketName {Avengers,Batman,Kimetsu}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  final TextEditingController _name = new TextEditingController();
  final TextEditingController _email = new TextEditingController();
  final TextEditingController _quantity = new TextEditingController();

  final formKey = GlobalKey<FormState>();
  String name = "";
  String email =  "";
  String quantity = "";
  String movieName = "";
  String ticketPrice = "";


  ticketName? _movieName = ticketName.Avengers;


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Form(
          key: formKey,
          child: Padding(
            padding: const EdgeInsets.symmetric (
              horizontal: 20,),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,

              children: <Widget>[
                const Text('Name',textAlign: TextAlign.left),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 5.0),
                ),

                TextFormField(
                  validator: (value) {
                    if(value!.isEmpty ){
                      return 'Please Enter Your Name';
                    }
                  },
                  onSaved: (value){
                    name = value!;
                  },
                  controller: _name,
                  decoration: InputDecoration(
                      hintText: '',
                      filled: true,
                      fillColor: Colors.black.withOpacity (0.2),
                      border: OutlineInputBorder(
                          borderSide: BorderSide.none,
                          borderRadius: BorderRadius.circular (10))),
                ),
                const SizedBox(
                  height: 5,
                ),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 5.0),
                ),

                const Text('Email',textAlign: TextAlign.left),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 5.0),
                ),

                TextFormField(
                  validator: (value) {
                    if(value!.isEmpty || !value.contains('@') || !value.contains('.com'))
                    {
                      return 'Email is Invalid';
                    }
                  },
                  onSaved: (value){
                    email = value!;
                  },
                  controller: _email,
                  decoration: InputDecoration(
                      hintText: '',
                      filled: true,
                      fillColor: Colors.black.withOpacity (0.2),
                      border: OutlineInputBorder(
                          borderSide: BorderSide.none,
                          borderRadius: BorderRadius.circular (10))),
                ),
                const SizedBox(
                  height: 5,
                ),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 10.0),
                ),


                //add radio button here
                const Text("Choose a Movie: "),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 10.0),
                ),

                Row(children: [

                  Radio(

                    value: ticketName.Avengers,
                    groupValue: _movieName,
                    onChanged: (ticketName?value){
                      setState(() {
                        _movieName = value;
                        movieName = 'Avengers (RM 20.00)';
                        ticketPrice = '20';
                      });
                    },

                  ),
                  const SizedBox (width: 5.0,),
                  const Text("Avengers (RM 20.00)"),
                ],),
                Row(children: [
                  //add radio button here
                  Radio(
                    value: ticketName.Batman,
                    groupValue: _movieName,
                    onChanged: (ticketName? value){
                      setState(() {
                        _movieName = value;
                        movieName = 'Batman (RM 10.00) ';
                        ticketPrice = '10';
                      });
                    },
                  ),
                  const SizedBox (width: 5.0,),
                  const Text("Batman (RM 10.00)"),
                ],),
                Row(children: [
                  //add radio button here
                  Radio(
                    value: ticketName.Kimetsu,
                    groupValue: _movieName,
                    onChanged: (ticketName? value){
                      setState(() {
                        _movieName = value;
                        movieName = 'Kimetsu No Yaiba (RM 12.00) ';
                        ticketPrice = '12';
                      });
                    },

                  ),
                  const SizedBox (width: 5.0,),
                  const Text("Kimetsu No Yaiba (RM 12.00)"),
                ],),


                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 10.0),
                ),

                const Text('Quantity',textAlign: TextAlign.left),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 5.0),
                ),

                TextFormField(
                  validator: (value) {
                    if(value!.isEmpty || value.length < 0){
                      return 'Please Enter the Correct Quantity';
                    }
                  },
                  onSaved: (value){
                    var quantity = int.parse(value!);
                  },
                  controller: _quantity,
                  decoration: InputDecoration(
                      hintText: 'Quantity',
                      filled: true,
                      fillColor: Colors.black.withOpacity (0.2),
                      border: OutlineInputBorder(
                          borderSide: BorderSide.none,
                          borderRadius: BorderRadius.circular (10))),
                ),
                const SizedBox(
                  height: 5,
                ),

                const Padding (
                  padding: EdgeInsets.symmetric(vertical: 10.0),
                ),

                ElevatedButton(
                  onPressed: (){
                    final isValid = formKey.currentState?.validate();
                    if(isValid!=null) {
                      formKey.currentState!.save();
                      Navigator.push(
                          context, MaterialPageRoute(builder: (context) => calculatePrice(name: _name.text, movieName: movieName, ticketPrice: ticketPrice, email: _email.text, quantity: _quantity.text)));
                    }
                  },
                  child: const Text('Calculate'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

calculate.dart

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

class calculatePrice extends StatelessWidget {

  late String name, email, movieName, ticketPrice, quantity;


  calculatePrice({required this.name, required this.email, required this.quantity, required this.movieName, required this.ticketPrice});


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("eTicket"),
      ),
      body: Center(
          child: Padding(
            padding: const EdgeInsets.symmetric (
              horizontal: 20,),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center ,
              crossAxisAlignment: CrossAxisAlignment.start,

              children: <Widget>[
                Text('Name : $name'),
                const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
                Text('Email $email'),
                const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
                Text('Movie : $movieName'),
                const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
                Text('Quantity $quantity'),
                const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
                Text('Total Price : ${int.parse(quantity) * int.parse(ticketPrice) }'),
                const Padding ( padding: EdgeInsets.symmetric(vertical: 10.0),),

                ElevatedButton(
                  onPressed: (){
                    Navigator.push(
                        context, MaterialPageRoute(builder: (context) =>  const MyApp()));
                  },
                  child: const Text('Back'),
                ),
              ],
            ),
          )
      ),
    );
  }
}

This is the answer based on the above code. Thank you for the suggestion and helps from the others.

main.dart

import 'package:flutter/material.dart';
import 'result.dart';
import 'customer.dart';
import 'movie.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'e-Ticket',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: const MyHomePage(title: 'Movie e-Ticket'),
    );
  }
}

enum SingingCharacter { avengers, batman, kimetsu }

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final txtName = TextEditingController();
  final txtEmail = TextEditingController();
  final txtQuantity = TextEditingController();
  SingingCharacter? _character = SingingCharacter.avengers;

  getPriceFromCharacter(SingingCharacter? character, int quantity) {
    switch (character) {
      case SingingCharacter.avengers:
        {
          return 20 * quantity;
        }
      case SingingCharacter.batman:
        {
          return 10 * quantity;
        }
      case SingingCharacter.kimetsu:
        {
          return 12 * quantity;
        }
    }
  }

  getMovieName(SingingCharacter? character) {
    switch (character) {
      case SingingCharacter.avengers:
        {
          return "Avengers";
        }
      case SingingCharacter.batman:
        {
          return "Batman";
        }
      case SingingCharacter.kimetsu:
        {
          return "Kimetsu";
        }
    }
  }

  // this to go to result screen and show the result
  void _gotoResultScreen() {
    int price = getPriceFromCharacter(_character, int.parse(txtQuantity.text));
    String movieName = getMovieName(_character);
    Customer c = Customer(txtName.text, txtEmail.text);
    Movie m = Movie(int.parse(txtQuantity.text), price, movieName);

    Navigator.push(
      context,
      MaterialPageRoute(
          builder: (context) => ResultPage(
            title: "Total Price",
            content: "Here is your details",
            customer: c,
            movie: m,
          )),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            const Text('Name', textAlign: TextAlign.left),


            TextField(
              controller: txtName,
              decoration: InputDecoration(
                hintText: '',
                filled: true,
                fillColor: Colors.green.withOpacity(0.2),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(10),
                  borderSide: BorderSide.none
                )
              ),
            ),
            const Text('Email'),
            TextField(
              controller: txtEmail,
              decoration: InputDecoration(
              hintText: '',
              filled: true,
              fillColor: Colors.green.withOpacity(0.2),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(10),
                borderSide: BorderSide.none
            ),)
            ),

            // This is for radio button in list tile
            const Text('Choose a movie:'),
            ListTile(
              title: const Text('AVENGERS(RM20)'),
              leading: Radio<SingingCharacter>(
                value: SingingCharacter.avengers,
                groupValue: _character,
                onChanged: (SingingCharacter? value) {
                  setState(() {
                    _character = value;
                  });
                },
              ),
            ),

            ListTile(
              title: const Text('BATMAN(RM10)'),
              leading: Radio<SingingCharacter>(
                  value: SingingCharacter.batman,
                  groupValue: _character,
                  onChanged: (SingingCharacter? value) {
                    setState(() {
                      _character = value;
                    });
                  }),
            ),

            ListTile(
              title: const Text('KIMETSU NO YAIBA(RM12)'),
              leading: Radio<SingingCharacter>(
                  value: SingingCharacter.kimetsu,
                  groupValue: _character,
                  onChanged: (SingingCharacter? value) {
                    setState(() {
                      _character = value;
                    });
                  }),
            ),

            // Input Quantity of the movie
            const Text('quantity'),
            TextField(
              controller: txtQuantity,
              decoration: InputDecoration(
                hintText: '',
                filled: true,
                fillColor: Colors.green.withOpacity(0.2),
                border: OutlineInputBorder(
                  borderSide: BorderSide.none,
                  borderRadius: BorderRadius.circular(10)
                )
              ),
            ),

            // When user click calculate Button
            ElevatedButton(
              onPressed: _gotoResultScreen,
              child: const Text('Calculate'),
            ),
          ],
        ),
      ),
    );
  }
}

movie.dart

class Movie {
  final int quantity;
  final int totalPrice;
  final String movieName;

  const Movie( this.quantity,this.totalPrice,this.movieName);
}

result.dart

import 'package:e_tickets/main.dart';
import 'package:flutter/material.dart';
import 'customer.dart';
import 'movie.dart';

class ResultPage extends StatefulWidget {
  const ResultPage({Key? key, required this.title, required this.content, required this.customer, required this.movie}) : super(key: key);

  final String title;
  final String content;
  final Customer customer;
  final Movie movie;

  @override
  State<ResultPage> createState() => _ResultPageState();
}

class _ResultPageState extends State<ResultPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,

          children: <Widget>[
            Text(widget.content,),
            const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
            Text("Name: " + widget.customer.name),
            const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
            Text("Email: " + widget.customer.email),
            const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
            Text("Quantity: " + widget.movie.quantity.toString()),
            const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
            Text("Movie Name: " + widget.movie.movieName),
            const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),
            Text("Total Price: RM" + widget.movie.totalPrice.toString()),
            const Padding ( padding: EdgeInsets.symmetric(vertical: 5.0),),

            ElevatedButton(
              onPressed: (){
                Navigator.push(
                    context, MaterialPageRoute(builder: (context) =>  const MyApp()));
              },
              child: const Text('Back'),
            ),
          ],
        ),
      ),
    );
  }
}

customer.dart

class Customer {
  final String name;
  final String email;

  const Customer(this.name, this.email);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM