Flutter :- How to display dynamic widgets on screen? - flutter

I want to show entered text in scrambled form. ie, each letter of the word need to display in individual Container in a row. For this, I am taking text input, storing it in List<String> and then scrambling it using shuffle() and then using List.generate to return Container with Text, as below:
List<Widget> _generateJumble(String input) {
inputList = input.split('');
var shuffleList = inputList.toList()..shuffle();
print(shuffleList);
return List<Widget>.generate(shuffleList.length, (int index) {
return Container(
width: 50,
color: Colors.blue,
child: Text(shuffleList[index].toString(),
style: TextStyle(color: Colors.white),
)
);
});
}
I am calling above method onTap of a button upon which the scrambled form of the input should be displayed. But I am not sure how to display the result of above method in UI. How should I use this method so that the returning Container based on shuffleList.length will be displayed in UI as below ?
RaisedButton(
onPressed: () {},
child: Text('Clear'),
)
],
),
),
Row(
children: <Widget>[
// ? _displayJumble()
]
)

This is my solution:
1) Press a button, scrable the string and set it to the a list
2) setState and show the list to the user
This is the widget code:
class _MyHomePageState extends State<MyHomePage> {
List<String> inputList = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Wrap(
children: inputList.map((s) {
return Container(
width: 50,
color: Colors.blue,
child: Text(
s,
style: TextStyle(color: Colors.white),
),
);
}).toList(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_generateJumble('Random string');
});
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
List<Widget> _generateJumble(String input) {
inputList = input.split('');
inputList = inputList.toList()..shuffle();
print(inputList);
}
}
I used the widget Wrap because automatically wrap the widget when there is no space available for it. You can use whatever you like to use.
This is the screen result:
Before press the button:
After press the button:

Please check the below solution of it, I have used the Wrap widget for it
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutterlearningapp/colors.dart';
class HomeScreen extends StatefulWidget {
var inputVales;
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
List<String> charcaterArray = new List<String>();
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: TextField(
decoration: InputDecoration(labelText: 'Enter Words'),
onChanged: (text) {
setState(() {
widget.inputVales = text;
charcaterArray.clear();
for (var i = 0; i < widget.inputVales.length; i++) {
var character = widget.inputVales[i];
if (character != " ") {
charcaterArray.add(character);
}
}
});
},
),
),
Wrap(
spacing: 6.0,
runSpacing: 6.0,
children:
List<Widget>.generate(charcaterArray.length, (int index) {
return Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.all(Radius.elliptical(4.0, 4.0)),
),
child: Center(
child: Text(
charcaterArray[index],
style:
TextStyle(color: Colors.deepOrange, fontSize: 20.0),
),
),
);
/*Chip(
label: Text(charcaterArray[index]),
onDeleted: () {
setState(() {
charcaterArray.removeAt(index);
});
},
);*/
}),
)
],
));
}
}
And here is the output of it

Related

Passing value to previous widget

I have simple form , inside it have CircularAvatar when this is pressed show ModalBottomSheet to choose between take picture from gallery or camera. To make my widget more compact , i separated it to some file.
FormDosenScreen (It's main screen)
DosenImagePicker (It's only CircularAvatar)
ModalBottomSheetPickImage (It's to show ModalBottomSheet)
The problem is , i don't know how to passing value from ModalBottomSheetPickImage to FormDosenScreen. Because value from ModalBottomSheetPickImage i will use to insert operation.
I only success passing from third Widget to second Widget , but when i passing again from second Widget to first widget the value is null, and i think the problem is passing from Second widget to first widget.
How can i passing from third Widget to first Widget ?
First Widget
class FormDosenScreen extends StatefulWidget {
static const routeNamed = '/formdosen-screen';
#override
_FormDosenScreenState createState() => _FormDosenScreenState();
}
class _FormDosenScreenState extends State<FormDosenScreen> {
String selectedFile;
#override
Widget build(BuildContext context) {
final detectKeyboardOpen = MediaQuery.of(context).viewInsets.bottom;
print('trigger');
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Tambah Dosen'),
actions: <Widget>[
PopupMenuButton(
itemBuilder: (_) => [
PopupMenuItem(
child: Text('Tambah Pelajaran'),
value: 'add_pelajaran',
),
],
onSelected: (String value) {
switch (value) {
case 'add_pelajaran':
Navigator.of(context).pushNamed(FormPelajaranScreen.routeNamed);
break;
default:
}
},
)
],
),
body: Stack(
fit: StackFit.expand,
children: <Widget>[
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(height: 20),
DosenImagePicker(onPickedImage: (file) => selectedFile = file),
SizedBox(height: 20),
Card(
margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextFormFieldCustom(
onSaved: (value) {},
labelText: 'Nama Dosen',
),
SizedBox(height: 20),
TextFormFieldCustom(
onSaved: (value) {},
prefixIcon: Icon(Icons.email),
labelText: 'Email Dosen',
keyboardType: TextInputType.emailAddress,
),
SizedBox(height: 20),
TextFormFieldCustom(
onSaved: (value) {},
keyboardType: TextInputType.number,
inputFormatter: [
// InputNumberFormat(),
WhitelistingTextInputFormatter.digitsOnly
],
prefixIcon: Icon(Icons.local_phone),
labelText: 'Telepon Dosen',
),
],
),
),
),
SizedBox(height: kToolbarHeight),
],
),
),
Positioned(
child: Visibility(
visible: detectKeyboardOpen > 0 ? false : true,
child: RaisedButton(
onPressed: () {
print(selectedFile);
},
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: colorPallete.primaryColor,
child: Text(
'SIMPAN',
style: TextStyle(fontWeight: FontWeight.bold, fontFamily: AppConfig.headerFont),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
textTheme: ButtonTextTheme.primary,
),
),
bottom: kToolbarHeight / 2,
left: sizes.width(context) / 15,
right: sizes.width(context) / 15,
)
],
),
);
}
}
Second Widget
class DosenImagePicker extends StatefulWidget {
final Function(String file) onPickedImage;
DosenImagePicker({#required this.onPickedImage});
#override
DosenImagePickerState createState() => DosenImagePickerState();
}
class DosenImagePickerState extends State<DosenImagePicker> {
String selectedImage;
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: InkWell(
onTap: () async {
await showModalBottomSheet(
context: context,
builder: (context) => ModalBottomSheetPickImage(
onPickedImage: (file) {
setState(() {
selectedImage = file;
widget.onPickedImage(selectedImage);
print('Hellooo dosen image picker $selectedImage');
});
},
),
);
},
child: CircleAvatar(
foregroundColor: colorPallete.black,
backgroundImage: selectedImage == null ? null : MemoryImage(base64.decode(selectedImage)),
radius: sizes.width(context) / 6,
backgroundColor: colorPallete.accentColor,
child: selectedImage == null ? Text('Pilih Gambar') : SizedBox(),
),
),
);
}
}
Third Widget
class ModalBottomSheetPickImage extends StatelessWidget {
final Function(String file) onPickedImage;
ModalBottomSheetPickImage({#required this.onPickedImage});
#override
Widget build(BuildContext context) {
return SizedBox(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: <Widget>[
InkWell(
onTap: () async {
final String resultBase64 =
await commonFunction.pickImage(quality: 80, returnFile: ReturnFile.BASE64);
onPickedImage(resultBase64);
},
child: CircleAvatar(
foregroundColor: colorPallete.white,
backgroundColor: colorPallete.green,
child: Icon(Icons.camera_alt),
),
),
InkWell(
onTap: () async {
final String resultBase64 =
await commonFunction.pickImage(returnFile: ReturnFile.BASE64, isCamera: false);
onPickedImage(resultBase64);
},
child: CircleAvatar(
foregroundColor: colorPallete.white,
backgroundColor: colorPallete.blue,
child: Icon(Icons.photo_library),
),
),
],
),
),
);
}
}
The cleanest and easiest way to do this is through Provider. It is one of the state management solutions you can use to pass values around the app as well as rebuild only the widgets that changed. (Ex: When the value of the Text widget changes). Here is how you can use Provider in your scenario:
This is how your model should look like:
class ImageModel extends ChangeNotifier {
String _base64Image;
get base64Image => _base64Image;
set base64Image(String base64Image) {
_base64Image = base64Image;
notifyListeners();
}
}
Don't forget to add getters and setters so that you can use notifyListeners() if you have any ui that depends on it.
Here is how you can access the values of ImageModel in your UI:
final model=Provider.of<ImageModel>(context,listen:false);
String image=model.base64Image; //get data
model.base64Image=resultBase64; //set your image data after you used ImagePicker
Here is how you can display your data in a Text Widget (Ideally, you should use Selector instead of Consumer so that the widget only rebuilds if the value its listening to changes):
#override
Widget build(BuildContext context) {
//other widgets
Selector<ImageModel, String>(
selector: (_, model) => model.base64Image,
builder: (_, image, __) {
return Text(image);
},
);
}
)
}
You could achieve this easily. If you are using Blocs.

Every checkboxes are being checked when you select only one of them

I've created a button that allows the user to add a credit card, the cards are being added to a Listview.builder.
The problem is that when I have multiple cards and I select one, it selects all of them, it's probably a state problems but I didn't find (yet) how to fix it, here is the dartpad : [dartpad][1] of my code if you can check it and maybe show me what I'm doing wrong, it's probably failing inside the buildBody but I'm not really sure and I have not successfully found a solution yet.
You simply have to tap two times on 'Add a card' and you will see when checking one of them, both will get selected.
For some reason the link isnt working through the shortcut so here it is https://dartpad.dev/b0aaaa2901aa3ac67426d9bdd885abb1:
I modified your dartpad code to get the behaviour you are trying to achive:
The code is provided below:
The issue was that you are using the same bool value _isSelected for the two Checkboxes.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: InformationsBancairesPage(),
),
),
);
}
}
class InformationsBancairesPage extends StatefulWidget {
#override
_InformationsBancairesPageState createState() =>
_InformationsBancairesPageState();
}
class _InformationsBancairesPageState extends State<InformationsBancairesPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(
'Payer ou recevoir un paiement'.toUpperCase(),
style: TextStyle(fontSize: 19, color: Colors.black),
),
centerTitle: true,
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.black),
),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: ListView(
children: <Widget>[
InputAddCarte(),
],
),
),
);
}
}
class InputAddCarte extends StatefulWidget {
#override
_InputAddCarteState createState() => _InputAddCarteState();
}
class _InputAddCarteState extends State<InputAddCarte> {
// create a list of bool values for your checkboxes
List<bool> _selectedList = [false, false];
int value = 0;
void initState() {
super.initState();
}
_addCard() {
setState(() {
value = value + 1;
print(value);
});
}
Widget buildBody(BuildContext context, int indexClicked) {
return LabeledCheckbox(
label: 'Card credit',
padding: const EdgeInsets.symmetric(horizontal: 20.0),
// pass the value of the checkbox at the selected index
value: _selectedList[indexClicked],
onChanged: (bool newValue) {
setState(() {
// pass the value of the checkbox at the selected index
_selectedList[indexClicked] = newValue;
});
},
);
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ButtonTheme(
minWidth: 250,
child: RaisedButton(
color: Color(0xff00cc99),
child: Text(
'ADD A CARD'.toUpperCase(),
style: TextStyle(color: Colors.white, fontSize: 18),
),
onPressed: _addCard,
),
),
// Show the cards when you press 'Ajouter une carte'
ListView.builder(
shrinkWrap: true,
itemCount: this.value,
itemBuilder: (BuildContext context, int value) {
// display two cards maximum
if (value < 2) {
// pass the index of the selected checkbox
return buildBody(context, value);
}
return Container();
},
),
ButtonTheme(
minWidth: 250,
child: RaisedButton(
color: Colors.orange,
child: Text(
'Delete a card'.toUpperCase(),
style: TextStyle(color: Colors.white, fontSize: 18),
),
onPressed: () {},
),
)
],
);
}
}
// Create custom checkbox for the list of cards
class LabeledCheckbox extends StatelessWidget {
const LabeledCheckbox({
this.label,
this.padding,
this.value,
this.onChanged,
});
final String label;
final EdgeInsets padding;
final bool value;
final Function onChanged;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
onChanged(!value);
},
child: Padding(
padding: padding,
child: Row(
children: <Widget>[
Expanded(child: Text(label)),
Checkbox(
value: value,
onChanged: (bool newValue) {
onChanged(newValue);
},
),
],
),
),
);
}
}

OnTap Function in the DropDownMenu Button in Flutter

I've tried to populate the dropdown menu button with the data from the SQLite database.
Then on the onTap Function I wanted to navigate to the selected category.
When I tap on the category it does not navigate.
I have saved each category with an id in the database which is used the identify the selected item.
Here is the code:
'''
class _HomeState extends State<Home> {
TodoService _todoService;
var _selectedValue;
var _categories = List<DropdownMenuItem>();
List<Todo>_todoList=List<Todo>();
#override
initState(){
super.initState();
_loadCategories();
}
_loadCategories() async {
var _categoryService = CategoryService();
var categories = await _categoryService.readCategory();
categories.forEach((category) {
setState(() {
_categories.add(DropdownMenuItem(
child: Text(category['name']),
value: category['name'],
onTap: ()=>Navigator.of(context).push(MaterialPageRoute(builder:(context)=>TodosByCategory(category: category['name'],))),
));
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _globalKey,
appBar: AppBar(
actions: <Widget>[
DropdownButtonHideUnderline(
child: DropdownButton(
value: _selectedValue,
items: _categories,
dropdownColor: Colors.blue,
style: TextStyle(color: Colors.white,fontSize: 16.0),
iconDisabledColor: Colors.white,
iconEnabledColor: Colors.white,
onChanged: (value) {
setState(() {
_selectedValue = value;
});
},
),
),
'''
Here is the todosByCategory():
'''
class _TodosByCategoryState extends State<TodosByCategory> {
List<Todo>_todoList=List<Todo>();
TodoService _todoService=TodoService();
#override
initState(){
super.initState();
getTodosByCategories();
}
getTodosByCategories()async{
var todos=await _todoService.readTodoByCategory(this.widget.category);
todos.forEach((todo){
setState(() {
var model= Todo();
model.title=todo['title'];
model.dueDate=todo['dueDate'];
_todoList.add(model);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos By Category'),
),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _todoList.length,
itemBuilder: (context, index){
return Padding(
padding: EdgeInsets.only(top:8.0, left: 8.0, right: 8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 8.0,
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(_todoList[index].title)
],
),
subtitle: Text(_todoList[index].dueDate),
// trailing: Text(_todoList[index].dueDate),
),
),
);
},),
)
],
),
);
}
}
'''
Please help me out.
Instead of writing the navigation code inside onTap of DropdownMenuItem, you can write it inside onChanged of DropdownButton where you are also getting the category name string as the value. It should work then.

I want to pass data from 2nd Screen to 1st Screen in flutter

I am making a simple TODO app and I wanted to pass data from 2nd Screen of my app to 1st screen. My first Screen is initially blank and there is nothing to display and it has a floating button to add a task. When it is clicked it takes to the Second page where user inputs the task and author and Clicks on "Submit" Button and takes us to 1st page where it gets Displayed. I want to pass data as List .I am trying everything for last 24 hours I implemented using ModalRoute and also created one instance of ToDo class so that it doesn't give NULL error but nothing is working out. I am attaching code So that you can understand my problem.
This is my FirstScreen()
import 'package:flutter/material.dart';
import 'todo.dart';
import 'todocard.dart';
class ToDos extends StatefulWidget{
#override
_ToDosState createState() => _ToDosState();
}
class _ToDosState extends State<ToDos> {
#override
Widget build(BuildContext context) {
List<ToDo> todos =[
];
final routeArgs = ModalRoute.of(context).settings.arguments as Map ;
todos.add(ToDo(author: routeArgs['task'],task: routeArgs['author']));
return Container(
child: Scaffold(
appBar: AppBar(
title: Text("TODO LIST"),
centerTitle: true,
),
body: Column(
children:todos.map((e) => ToDoCard(
todo: e,
)).toList(),
//ToDoCard is just a Card widget
),
floatingActionButton: FloatingActionButton(
elevation: 0.0,
child: Text("+"),
onPressed: ()
{
Navigator.pushNamed(context, '/add_task');
},
),
),
);
}
}
My SecondScreen is :
import 'package:flutter/material.dart';
class AddTask extends StatefulWidget {
#override
_AddTaskState createState() => _AddTaskState();
}
class _AddTaskState extends State<AddTask> {
#override
Widget build(BuildContext context) {
String author,task;
return Container(
child: Scaffold(
appBar: AppBar(
title: Text("ADD TASK"),
centerTitle: true,
),
body: Column(
children: <Widget>[
Text("Enter Your Task"),
TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'task'
),
onChanged: (text){
task = text;
},
),
TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'author'
),
onChanged: (text){
author = text;
},
),
Row(
children: <Widget>[
RaisedButton(
onPressed: () {
Navigator.pop(context, {
'author': author,
'task': task,
});
},
child: Text("Submit"),
),
SizedBox(width: 10.0,),
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancel"),
),
],
)
],
),
));
}
}
The main.dart is as Follows:
import 'package:flutter/material.dart';
import 'todo.dart';
import 'add_task.dart';
import 'display_todo.dart';
void main() {
runApp(MaterialApp(
title: 'Passing Data',
initialRoute: '/',
routes: {
'/': (context) => ToDos(),
'/add_task': (context) => AddTask(),
},
));
}
The ToDoCard for displaying the info as Card:
import 'todo.dart';
import 'package:flutter/material.dart';
class ToDoCard extends StatelessWidget {
final ToDo todo;
ToDoCard({this.todo});
#override
Widget build(BuildContext context) {
return Card(
color: Colors.cyan,
margin: EdgeInsets.fromLTRB(20, 20, 20, 0),
child: Padding(
padding: EdgeInsets.fromLTRB(13, 10, 13, 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
todo.author,
style: TextStyle(
color: Colors.black,
fontSize: 20.0,
),
),
SizedBox(height: 10.0,),
Text(
todo.task,
style: TextStyle(
color: Colors.black,
fontSize: 20.0,
),
),
SizedBox(height: 10.0,),
// RaisedButton.icon(onPressed: delete, icon: Icon(Icons.delete), label:
Text("Delete quote"), color: Colors.red,),
],
),
),
);
}
}
ToDo class:
class ToDo{
final String task;
final String author;
ToDo({this.task,this.author});
}
You can pass the result back on the Navigator.pop() and retrieve it by awaiting the pushNamed call.
Retrieve value in Page 1:
onPressed: () async
{
dynamic result = await Navigator.pushNamed(context, '/add_task');
if(result != null) {
setState(() {todos.add(result);});
}
},
Pass value from page 2 in the submit button
onPressed: () {
Navigator.pop(context, ToDo(task: task, author: author));
},

how display x numbers of widget in flutter

EDIT :
Here is my result now :
As you can see i have make a lot of work and now it is good Advanced. Now i have the 5 Numbers selected (5-34-37-42-49) in red just at top of the 2 green buttons. For the moment the function getWidget return the 5 Numbers in red using gridview again but not sure it is what i need to use. Can you help me for resolve the problem with the size of the 5 circles, i need it centered and not use scroll.
Here is my complete code Under :
import 'package:flutter/material.dart';
import 'dart:math';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'package:flutter_app/menu_member.dart';
import 'package:flutter_app/globals.dart' as globals;
class Lotto extends StatefulWidget {
#override
_LottoState createState() => new _LottoState();
}
class _LottoState extends State<Lotto> {
#override
void initState() {
super.initState();
}
var i=1;
var nb_num=49;
var no_select=[];
var no_a_select=5;
List<Color> colorList = List<Color>.generate(49, (int index) => Colors.lightBlue);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: new AppBar(
title: new Text('GRILLE DE LOTTO'),
),
body:
Center(
child: Column(
children: <Widget>[
Container(
width:400,
height:30,
margin: const EdgeInsets.only(top: 10.0),
child : new Text("Selectionnez 5 numéros",textAlign: TextAlign.center,style: TextStyle(fontSize: 30.0),),
),
Container(
width:400,
height:300,
child: new GridView.count(
crossAxisCount: 9,
padding: const EdgeInsets.all(30.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: new List<Widget>.generate(49, (index) {
return new GestureDetector(
onTap: () {
setState(() {
if (colorList[index] == Colors.lightBlue) {
if (no_select.length<no_a_select) {
colorList[index] = Colors.redAccent;
no_select.add(index+1);
}
else {
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
title: Text("INFORMATION"),
content: Text("Vous ne pouvez pas sélectionner plus de 5 numéros !!!"),
);
}
);
}
print(no_select);
}
else {
colorList[index] = Colors.lightBlue;
no_select.remove(index+1);
print(no_select);
}
});
},
child: Container(
child: ClipOval(
child: Container(
color: colorList[index],
height: 20.0,
width: 20.0,
child: Center(
child: new Text((index+1).toString(),
style: TextStyle(color: Colors.white, fontSize: 24),
textAlign: TextAlign.center),
),
),
),
),
);
}
),
),
),
Container(
width:400,
height:30,
margin: const EdgeInsets.only(top: 10),
child : new Text("Vos Numéros",textAlign: TextAlign.center,style: TextStyle(fontSize: 30.0),),
),
Container(
width:400,
height:80,
margin: const EdgeInsets.only(top: 10.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.lightBlueAccent,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
child:
getWidget()
),
Container(
width:300,
height:45,
margin: const EdgeInsets.only(top: 10.0),
child:
RaisedButton(
color: Colors.green,
textColor: Colors.white,
padding: EdgeInsets.fromLTRB(9, 9, 9, 9),
child: Text('TIRAGE ALEATOIRE'),
onPressed: () {
Select_numbers();
},
),
),
Container(
width:300,
height:45,
margin: const EdgeInsets.only(top: 10.0),
child:
RaisedButton(
color: Colors.green,
textColor: Colors.white,
padding: EdgeInsets.fromLTRB(9, 9, 9, 9),
child: Text('VALIDER VOTRE GRILLE'),
onPressed: () {
Valide_grille();
},
),
),
]
)
),
),
);
}
getWidget() {
if (no_select.length==0) {
return Text("Pas de numéros");
}
else {
return GridView.count(
crossAxisCount: 5,
padding: const EdgeInsets.all(10.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: new List<Widget>.generate(no_select.length, (index) {
return ClipOval(
child: Container(
color: Colors.red,
height: 20.0,
width: 20.0,
child: Center(
child: new Text((no_select[index].toString()),
style: TextStyle(color: Colors.white, fontSize: 24),
textAlign: TextAlign.center),
),
),
);
}
)
);
}
}
Select_numbers() {
setState(() {
var j = 1;
var num_sel;
var pos_sel;
no_select=[];
colorList=[];
colorList=List<Color>.generate(49, (int index) => Colors.lightBlue);
var rng = new Random();
List tab=[];
tab = List.generate(49, (int index) => index + 1);
print (tab);
while (j <= no_a_select) {
pos_sel = rng.nextInt(tab.length-1);
num_sel=tab[pos_sel];
no_select.add(num_sel);
colorList[num_sel-1] = Colors.redAccent;
tab.remove(num_sel);
print(tab);
j++;
}
print(no_select);
});
}
Future Valide_grille() async{
// For CircularProgressIndicator.
bool visible = false ;
// Showing CircularProgressIndicator.
setState(() {
visible = true ;
});
// SERVER LOGIN API URL
var url = 'https://www.easytrafic.fr/game_app/valide_lotto.php';
// Store all data with Param Name.
var data = {'id_membre':globals.id_membre, 'result':no_select};
print (data);
var grille_encode=jsonEncode(data);
print(grille_encode);
// Starting Web API Call.
var response = await http.post(url, body: grille_encode,headers: {'content-type': 'application/json','accept': 'application/json','authorization': globals.token});
print(response.body);
// Getting Server response into variable.
var message = json.decode(response.body);
// If the Response Message is Matched.
if(message == 'OK')
{
print('VALIDATION DE LA GRILLE OK');
// Hiding the CircularProgressIndicator.
setState(() {
visible = false;
});
}else{
// Hiding the CircularProgressIndicator.
setState(() {
visible = false;
});
// Showing Alert Dialog with Response JSON Message.
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(message),
actions: <Widget>[
FlatButton(
child: new Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
}
I think that you need a Flutter simple Alert Dialog instead of print command. So change your code :
print(
"Vous ne pouvez pas sélectionner plus de 5 numéros !!!");
to:
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
title: Text("Alert Dialog"),
content: Text("Vous ne pouvez pas sélectionner plus de 5 numéros !!!"),
);
}
);
Because print command sends its output to console.
I suggest you read this: https://dev.to/mightytechno/flutter-alert-dialog-to-custom-dialog-1ok4
Edit:
In order to have 49 circles between the buttons, you need move these lines of your code:
Expanded(
flex:2,
child:
RaisedButton(
color: Colors.green,
textColor: Colors.white,
padding: EdgeInsets.fromLTRB(9, 9, 9, 9),
child: Center(child: Text('TIRAGE ALEATOIRE')),
onPressed: () {
Select_numbers();
},
),
),
after these lines:
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: new AppBar(
title: new Text('GRILLE DE LOTTO'),
),
body:
Center(
child: Column(
children: <Widget>[
Also in order to make a RaisedButton's corners rounded, you can add this code:
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),),
after RaisedButton(
You can copy paste run full code below
You can use List to keep color of each number
code snippet
List<Color> colorList = List<Color>.generate(49, (int index) => Colors.lightBlue);
...
setState(() {
if (colorList[index] == Colors.lightBlue) {
if (no_select.length < no_a_select) {
colorList[index] = Colors.redAccent;
...
child: Container(
color: colorList[index],
working demo
full code
import 'package:flutter/material.dart';
class Lotto extends StatefulWidget {
#override
_LottoState createState() => new _LottoState();
}
class _LottoState extends State<Lotto> {
Color color;
void message() {
print('Clicked');
}
List<Color> colorList = List<Color>.generate(49, (int index) => Colors.lightBlue);
#override
void initState() {
super.initState();
color = Colors.lightBlue;
print(colorList[0].toString());
}
var i = 1;
var nb_num = 49;
var no_select = [];
var no_a_select = 5;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: <Widget>[
Expanded(
flex: 3,
child: new GridView.count(
crossAxisCount: 7,
children: new List<Widget>.generate(49, (index) {
return new GestureDetector(
onTap: () {
setState(() {
if (colorList[index] == Colors.lightBlue) {
if (no_select.length < no_a_select) {
colorList[index] = Colors.redAccent;
no_select.add(index + 1);
} else {
print(
"Vous ne pouvez pas sélectionner plus de 5 numéros !!!");
}
print(no_select);
} else {
colorList[index] = Colors.lightBlue;
no_select.remove(index + 1);
print(no_select);
}
});
},
child: Container(
child: ClipOval(
child: Container(
color: colorList[index],
height: 20.0,
width: 20.0,
child: Center(
child: new Text((index + 1).toString(),
style: TextStyle(color: Colors.white, fontSize: 24),
textAlign: TextAlign.center),
),
),
),
),
);
}),
),
),
Expanded(flex: 1, child: Text("abc")),
],
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Lotto(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}