i have a Flutter app which should show a counting down timer in an alert box for Phone code confirming (i need this timer to resend the code to my user when 60 second is up) , i start timer when i click on Confirm Button , but the problem is that the timer is not showing that he's going down he stills with a fixed value.
here is my alert box
Alert Box with timer NOT SHOWING COUNT DOWN
here is my timer Function :
int _counter = 60;
Timer _timer;
void _startTimer(){
_counter = 60;
if(_timer != null){
_timer.cancel();
}
_timer = Timer.periodic(Duration(seconds: 1), (timer){
setState(() {
(_counter > 0) ? _counter-- : _timer.cancel();
});
});
}
here is my alert Box code :
void alertD(BuildContext ctx) {
var alert = AlertDialog(
// title: Center(child:Text('Enter Code')),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
backgroundColor: Colors.grey[100],
elevation: 0.0,
content: Container(
height: 215,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 15),
child: Text(
'Enter Code',
style: TextStyle(
color: Colors.green[800],
fontWeight: FontWeight.bold,
fontSize: 16
),
)),
Container(
height: 70,
width: 180,
child: TextFormField(
style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green, width: 0.0)),
),
keyboardType: TextInputType.number,
maxLength: 10,
),
),
SizedBox(
height: 1,
),
Text('00:$_counter'),
SizedBox(height: 15,)
,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {
Navigator.of(ctx).pushNamed(SignUpScreenSecond.routeName);
},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.green,
Colors.grey,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Validate',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
),
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.grey,
Colors.green,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Resend',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
)
],
), //new column child
],
),
));
showDialog(
context: ctx,
builder: (BuildContext c) {
return alert;
});
}
that's how i'm calling my alert dialog and my timer when i click Confirm Button :
onTap: () {
_startTimer;
alertD(context);
},
You can copy paste run full code below
You can use StreamBuilder and StreamController
AlertDialog content continually receive stream int from Timer
code snippet
StreamController<int> _events;
#override
initState() {
super.initState();
_events = new StreamController<int>();
_events.add(60);
}
...
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
(_counter > 0) ? _counter-- : _timer.cancel();
print(_counter);
_events.add(_counter);
});
...
content: StreamBuilder<int>(
stream: _events.stream,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
...
Text('00:${snapshot.data.toString()}'),
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
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;
StreamController<int> _events;
#override
initState() {
super.initState();
_events = new StreamController<int>();
_events.add(60);
}
Timer _timer;
void _startTimer() {
_counter = 60;
if (_timer != null) {
_timer.cancel();
}
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
//setState(() {
(_counter > 0) ? _counter-- : _timer.cancel();
//});
print(_counter);
_events.add(_counter);
});
}
void alertD(BuildContext ctx) {
var alert = AlertDialog(
// title: Center(child:Text('Enter Code')),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
backgroundColor: Colors.grey[100],
elevation: 0.0,
content: StreamBuilder<int>(
stream: _events.stream,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
print(snapshot.data.toString());
return Container(
height: 215,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 15),
child: Text(
'Enter Code',
style: TextStyle(
color: Colors.green[800],
fontWeight: FontWeight.bold,
fontSize: 16),
)),
Container(
height: 70,
width: 180,
child: TextFormField(
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green, width: 0.0)),
),
keyboardType: TextInputType.number,
maxLength: 10,
),
),
SizedBox(
height: 1,
),
Text('00:${snapshot.data.toString()}'),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {
//Navigator.of(ctx).pushNamed(SignUpScreenSecond.routeName);
},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.green,
Colors.grey,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Validate',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
),
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.grey,
Colors.green,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Resend',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
)
],
), //new column child
],
),
);
}));
showDialog(
context: ctx,
builder: (BuildContext c) {
return alert;
});
}
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>[
RaisedButton(
onPressed: () {
_startTimer();
alertD(context);
},
child: Text('Click')),
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),
),
);
}
}
Related
I have a form consisting of nextformfield and elevatedButton. I want to repeat the same form just below on the screen in the same page. I have never tried to do this and it didn't work out, please help.
Here is my code in which I want to do this:
import 'dart:math';
import 'package:flutter/material.dart';
class gradysu extends StatefulWidget {
const gradysu({super.key});
#override
State<gradysu> createState() => _gradysuState();
}
class _gradysuState extends State<gradysu> {
var _formKey = GlobalKey<FormState>();
var x, y, c, d;
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Квадрат'),
backgroundColor: Color.fromARGB(255, 252, 252, 252),
automaticallyImplyLeading: true,
),
body: SingleChildScrollView(
child: Container(
height: 800,
width: 639,
/* decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/image/fon2.png"),
fit: BoxFit.cover,
),
),*/
child: Column(
children: [
Container(
color: Colors.brown,
height: 50.0,
width: 1000.0,
child: Center(
child: const Text(
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Colors.white),
'Расчёт площади квадрата S=:'))),
Row(children: <Widget>[
Container(
padding: const EdgeInsets.all(10.0),
child: const Text('Введите градусы:',
style: TextStyle(color: Color.fromARGB(255, 0, 0, 0))),
),
Expanded(
child: Container(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) return 'Задайте градусы';
try {
x = double.parse(value);
} catch (h) {
x;
return h.toString();
}
}))),
]),
const SizedBox(height: 20.0),
Text(
y == null ? '' : ' $y (рад) ',
style: const TextStyle(
fontSize: 20.0, color: Color.fromARGB(255, 0, 0, 0)),
),
const SizedBox(height: 20.0),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
setState(() {
if (x is double) y = ((x * pi) / 180);
});
}
},
style: ElevatedButton.styleFrom(
foregroundColor: Color.fromARGB(255, 235, 235,
235), //change background color of button
backgroundColor:
Colors.brown, //change text color of button
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
elevation: 5.0,
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Text(
'Вычислить',
style: TextStyle(fontSize: 20),
))),
SizedBox(height: 10.0),
],
),
),
),
),
);
}
}
class gradysu1 extends StatefulWidget {
const gradysu1({super.key});
#override
State<gradysu1> createState() => _gradysu1State();
}
class _gradysu1State extends State<gradysu1> {
var _formKey1 = GlobalKey<FormState>();
var a, c;
#override
Widget build(BuildContext context) {
return Form(
key: _formKey1,
child: Scaffold(
body: SafeArea(
child: Column(children: [
Row(children: <Widget>[
Container(
padding: const EdgeInsets.all(10.0),
child: const Text('Введите градусы:',
style: TextStyle(color: Color.fromARGB(255, 0, 0, 0))),
),
Expanded(
child: Container(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) return 'Задайте градусы';
try {
a = double.parse(value);
} catch (h) {
a;
return h.toString();
}
}))),
]),
const SizedBox(height: 20.0),
Text(
a == null ? '' : ' $a (рад) ',
style: const TextStyle(
fontSize: 20.0, color: Color.fromARGB(255, 0, 0, 0)),
),
const SizedBox(height: 20.0),
ElevatedButton(
onPressed: () {
if (_formKey1.currentState!.validate()) {
setState(() {
if (c is double) a = ((c * pi) / 180);
});
}
},
style: ElevatedButton.styleFrom(
foregroundColor: Color.fromARGB(
255, 235, 235, 235), //change background color of button
backgroundColor: Colors.brown, //change text color of button
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
elevation: 5.0,
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Text(
'Вычислить',
style: TextStyle(fontSize: 20),
))),
]))));
}
}
This is what it looks like
And this is how it should look like
I tried to create another class, but flutter just doesn't see it, I tried to add it to the main code, but then he just didn't count, but threw an exception.
Try to create reusable widget or builder method to minimize the snippet/code-dublication.
import 'dart:math';
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MaterialApp(
home: gradysu(),
));
}
class gradysu extends StatefulWidget {
const gradysu({super.key});
#override
State<gradysu> createState() => _gradysuState();
}
class _gradysuState extends State<gradysu> {
var _formKey = GlobalKey<FormState>();
var x, y, c, d;
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Квадрат'),
backgroundColor: Color.fromARGB(255, 252, 252, 252),
automaticallyImplyLeading: true,
),
body: SingleChildScrollView(
child: Container(
height: 800,
width: 639,
/* decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/image/fon2.png"),
fit: BoxFit.cover,
),
),*/
child: Column(
children: [
Container(
color: Colors.brown,
child: Center(
child: const Text(
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Colors.white),
'Расчёт площади квадрата S=:'))),
Row(children: <Widget>[
Container(
padding: const EdgeInsets.all(10.0),
child: const Text('Введите градусы:',
style: TextStyle(color: Color.fromARGB(255, 0, 0, 0))),
),
Expanded(
child: Container(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) return 'Задайте градусы';
try {
x = double.parse(value);
} catch (h) {
x;
return h.toString();
}
},
),
),
),
]),
const SizedBox(height: 20.0),
Text(
y == null ? '' : ' $y (рад) ',
style: const TextStyle(
fontSize: 20.0, color: Color.fromARGB(255, 0, 0, 0)),
),
const SizedBox(height: 20.0),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
setState(() {
if (x is double) y = ((x * pi) / 180);
});
}
},
style: ElevatedButton.styleFrom(
foregroundColor: Color.fromARGB(
255, 235, 235, 235), //change background color of button
backgroundColor: Colors.brown, //change text color of button
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
elevation: 5.0,
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Text(
'Вычислить',
style: TextStyle(fontSize: 20),
),
),
),
SizedBox(height: 10.0),
/// second item , you can create a build method for this
Row(children: <Widget>[
Container(
padding: const EdgeInsets.all(10.0),
child: const Text('Введите градусы:',
style: TextStyle(color: Color.fromARGB(255, 0, 0, 0))),
),
Expanded(
child: Container(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) return 'Задайте градусы';
try {
x = double.parse(value);
} catch (h) {
x;
return h.toString();
}
},
),
),
),
]),
const SizedBox(height: 20.0),
Text(
y == null ? '' : ' $y (рад) ',
style: const TextStyle(
fontSize: 20.0, color: Color.fromARGB(255, 0, 0, 0)),
),
const SizedBox(height: 20.0),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
setState(() {
if (x is double) y = ((x * pi) / 180);
});
}
},
style: ElevatedButton.styleFrom(
foregroundColor: Color.fromARGB(
255, 235, 235, 235), //change background color of button
backgroundColor: Colors.brown, //change text color of button
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
elevation: 5.0,
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Text(
'Вычислить',
style: TextStyle(fontSize: 20),
),
),
),
SizedBox(height: 10.0),
],
),
),
),
),
);
}
}
I use hive to store my data locally in expense tracker app. I have saved all expenses in a box called expenseBox. I have given each expense item a date and I want items with the same date to be grouped together and displayed separately. Is there a way to achieve this?
Thanks for your help!
BTW this is the code for my homescreen where I display the items.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:flutter_locales/flutter_locales.dart';
import '/models/expense.dart';
import '/widgets/expense_list_tile.dart';
import '/screens/add_expense_screen.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
static const routeName = '/home_page';
#override
_HomeScreenState createState() => _HomeScreenState();
}
enum SlidableAction {
edit,
delete,
}
class _HomeScreenState extends State<HomeScreen> {
late Box expenseBox;
late Box pocketBox;
bool isFabVisible = true;
#override
void initState() {
expenseBox = Hive.box<Expense>('expenses');
pocketBox = Hive.box<int>('pocket');
super.initState();
}
#override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: Hive.box<int>('pocket').listenable(),
builder: (context, Box<int> pocketBox, child) => Scaffold(
appBar: AppBar(
title: const LocaleText('appName'),
elevation: 0,
centerTitle: true,
),
body: NestedScrollView(
headerSliverBuilder: (context, _) => [
SliverAppBar(
expandedHeight: MediaQuery.of(context).size.height * 0.15,
flexibleSpace: FlexibleSpaceBar(
background: Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const LocaleText(
'appName',
style: TextStyle(
fontSize: 14, color: Colors.white),
),
Text(
'${pocketBox.get('budget') ?? 0}',
style: const TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const LocaleText(
'income',
style: TextStyle(
fontSize: 14, color: Colors.white),
),
Text(
'${pocketBox.get('totalIncome') ?? 0}',
style: const TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const LocaleText(
'expense',
style: TextStyle(
fontSize: 14, color: Colors.white),
),
Text(
'${pocketBox.get('totalExpense') ?? 0}',
style: const TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
],
),
),
Expanded(child: Container()),
],
),
),
),
),
],
body: ValueListenableBuilder(
valueListenable: Hive.box<Expense>('expenses').listenable(),
builder: (context, Box<Expense> expensesBox, child) {
return NotificationListener<UserScrollNotification>(
onNotification: (notification) {
if (notification.direction == ScrollDirection.forward) {
if (!isFabVisible) setState(() => isFabVisible = true);
} else if (notification.direction ==
ScrollDirection.reverse) {
if (isFabVisible) setState(() => isFabVisible = false);
}
return true;
},
child: Scrollbar(
thickness: 5,
interactive: true,
child: ListView.separated(
separatorBuilder: (context, index) {
return const SizedBox();
},
itemCount: expenseBox.length,
itemBuilder: (context, index) {
final expense = expenseBox.getAt(index);
return ExpenseListTile(index: index, expense: expense);
},
),
),
);
},
),
),
floatingActionButton: isFabVisible
? FloatingActionButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const AddExpenseScreen(
index: -1,
),
));
},
child: const Icon(Icons.add),
)
: null,
),
);
}
}
You can try this code.
import 'package:flutter/material.dart';
import 'package:sticky_grouped_list/sticky_grouped_list.dart';
class MyMissionList extends StatefulWidget {
#override
State<MyMissionList> createState() => _MyMissionListState();
}
class _MyMissionListState extends State<MyMissionList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(150.0),
child: Container(
decoration: BoxDecoration(
color: AppColors.baseLightBlueColor,
// AppColors.blue,
borderRadius: BorderRadius.only(bottomRight: Radius.circular(30)),
),
child: Material(
color: AppColors.baseLightBlueColor,
elevation: 15,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.only(bottomRight: Radius.circular(30)),
),
child: Column(
children: [
AppBar(
backgroundColor: AppColors.baseLightBlueColor,
elevation: 0.0,
actions: [
Container(
padding: EdgeInsets.only(right: 20),
child: Image.asset(
"assets/Vector-2.png",
height: 5,
width: 22,
color: Colors.white,
)),
],
),
Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(left: 20),
margin: EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
color: AppColors.baseLightBlueColor,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Hello User123,",
style:
TextStyle(color: AppColors.white, fontSize: 15),
),
SizedBox(height: 10),
Text(
AppStrings.totalAmount,
// "Montant total :",
style:
TextStyle(color: AppColors.white, fontSize: 11),
),
Text(
"592,30 €",
style:
TextStyle(color: AppColors.white, fontSize: 25),
),
],
),
)
],
),
),
)),
body: Column(
children: [
Padding(
padding: const EdgeInsets.only(left:15.0,right: 15,top: 15),
child: Text("My Mission",style: TextStyle(
color: Color(0xff243656),
fontSize: 15,
fontWeight: FontWeight.w300),
),
),
Expanded(
child: StickyGroupedListView<Element, DateTime>(
elements: elements,
order: StickyGroupedListOrder.ASC,
groupBy: (Element element) =>
DateTime(element.date.year, element.date.month, element.date.day),
groupComparator: (DateTime value1, DateTime value2) =>
value2.compareTo(value1),
itemComparator: (Element element1, Element element2) =>
element1.date.compareTo(element2.date),
floatingHeader: false,
groupSeparatorBuilder: (Element element) => Container(
height: 50,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 220,
padding: EdgeInsets.only(left: 20,top: 20,bottom: 10),
child: Text(
'${element.heading}',
textAlign: TextAlign.start,
style: TextStyle(color: Color(0xff919AAA)),
),
),
],
),
),
itemBuilder: (_, Element element) {
return element.type
? GestureDetector(
onTap: () {
// Navigator.push(context, MaterialPageRoute(builder: (context)=> WaitingForValidation()));
},
child: Card(
elevation: 4,
margin: EdgeInsets.only(bottom: 15, right: 15, left: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
height: 70,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: AppColors.white),
child: Row(
children: [
Container(
width: MediaQuery.of(context).size.width * 0.62,
height: 50,
padding: EdgeInsets.only(top: 10,left: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
element.subTitle +
'${element.date.day}/${element.date.month}/'
'${element.date.year}',
style: TextStyle(
//color:AppColors.grey
color: Color(0xff919AAA),
fontSize: 12,
fontWeight: FontWeight.w300),
),
SizedBox(height: 2,),
Text(
element.hotelName,
style: TextStyle(
//color:AppColors.grey
color: Color(0xff243656),
fontSize: 15,
fontWeight: FontWeight.w300),
),
],
),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Card(
elevation: 15.0,
shadowColor: Colors.blue[100],
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20.0))),
child: Container(
height: 30,
width: 80,
decoration: BoxDecoration(
// boxShadow: [BoxShadow(color: AppColors.grey, blurRadius: 20.0)],
borderRadius:
BorderRadius.circular(20.0),
gradient: LinearGradient(
colors: [
Colors.blue,
Colors.blue.shade900,
],
)),
child: MaterialButton(
onPressed: () {},
child: Text(
element.buttonText,
style: TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.bold),
),
),
),
),
),
],
),
),
),
)
: Card(
elevation: 4,
margin: EdgeInsets.only(bottom: 15, right: 15, left: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Container(
height: 70,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: AppColors.white),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: MediaQuery.of(context).size.width * 0.62,
height: 50,
padding: EdgeInsets.only(top: 10,left: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
element.subTitle +
'${element.date.day}/${element.date.month}/'
'${element.date.year}',
style: TextStyle(
//color:AppColors.grey
color: Color(0xff919AAA),
fontSize: 12,
fontWeight: FontWeight.w300),
),
SizedBox(height: 2,),
Text(
element.hotelName,
style: TextStyle(
//color:AppColors.grey
color: Color(0xff243656),
fontSize: 15,
fontWeight: FontWeight.w300),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top:5.0,bottom: 5),
child: Container(
height: 30,
width: 95,
child: MaterialButton(
onPressed: () {},
child: Text(
element.buttonText,
style: TextStyle(
color: AppColors.green,
fontSize: 14,
fontWeight: FontWeight.bold),
),
),
),
)
],
),
),
);
},
),
),
],
),
);
}
}
class Element {
bool type;
DateTime date;
String hotelName;
String subTitle;
String heading;
String buttonText;
Element(this.date, this.type, this.hotelName, this.subTitle, this.heading,
this.buttonText);
}
List<Element> elements = <Element>[
Element(
DateTime(2020, 7, 22),
false,
"Rendez-vous equipe prod",
"Jeudi",
"Terminate",
"Terminate",
),
Element(
DateTime(2021, 10, 15),
false,
"Rendez-vous equipe prod",
"Jeudi",
"Terminate",
"Terminate",
),
Element(
DateTime(2021, 10, 15),
false,
"Rendez-vous equipe prod",
"Jeudi",
"Terminate",
/**/
"Terminate",
),
Element(
DateTime(2021, 12, 12),
true,
"Visite entrepot Villabe ",
"Mercredi",
"To Plan",
"To Plan",
),
];
I have implemented BLOC architecture for a user profile edit for a logged in user in flutter. The inputs are filled with user's existing info which I got from the API. But whenever input is focused and keyboard closes the entered value gets replaced with the initial value which I got from the API response.
This is my View profile UI
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:payd/services/profile_service.dart';
import 'package:payd/bloc/profile_bloc.dart';
import 'package:payd/model/profile_model.dart';
void main() {
runApp(EditProfile());
}
class EditProfile extends StatefulWidget {
#override
_EditProfilesState createState() => _EditProfilesState();
}
class _EditProfilesState extends State<EditProfile>
with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Image.asset('assets/logo.png', fit: BoxFit.cover),
actions: [
IconButton(
onPressed: () {},
icon: Image.asset('assets/Icon feather-bell.png'),
iconSize: 30,
),
],
elevation: 5,
),
backgroundColor: Color(0xFF33138C),
body: BlocProvider(
create: (context) => ProfileBloc(ProfileService()),
child: Body(),
),
);
}
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
class Body extends StatelessWidget {
static final _formKey = GlobalKey<FormState>();
void _submit() {
final isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
_formKey.currentState.save();
}
#override
Widget build(BuildContext context) {
final textFieldFocusNode = FocusNode();
final profileBloc = BlocProvider.of<ProfileBloc>(context);
var userSlug = '52q6x93k4y';
profileBloc.add(FetchProfile(userSlug));
Size size = MediaQuery.of(context).size;
return Container(
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(
image: DecorationImage(
image: new ExactAssetImage('assets/app-background.png'),
fit: BoxFit.cover)),
child: Padding(
padding: const EdgeInsets.all(0),
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
children: <Widget>[
SizedBox(
height: size.height,
child: Stack(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: size.height * 0.04),
// height: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0),
topRight: Radius.circular(40.0),
),
),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Column(
children: [
Container(
padding: EdgeInsets.only(
top: 30.0,
left: 20.0, bottom: 25.0),
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.keyboard_arrow_left),
iconSize: 30,
),
),
],
),
Column(
children: [
Container(
padding: EdgeInsets.only(
top: 30.0,
right: 30.0, bottom: 25.0),
alignment: Alignment.centerLeft,
child: Text(
'Edit Account',
style: const TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.w600,
color: Colors.black54),
),
),
],
),
],
),
BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
print(state);
if (state is ProfileIsLoaded) {
return Container(
child: Flexible(
child: SingleChildScrollView(
reverse: true,
padding:
EdgeInsets.only(left: 16, right: 16),
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(
bottom:
size.height > 700
? 20
: 15),
padding: EdgeInsets.only(
left: 20.0,
right: 20.0,
bottom: 25.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: TextEditingController(
text: state.getProfile.firstName),
decoration: InputDecoration(
labelText: 'First Name'),
keyboardType: TextInputType
.name,
onFieldSubmitted: (
value) {
//Validator
},
validator: (value) {
if (value.isEmpty) {
return 'Required';
}
return null;
},
),
//box styling
SizedBox(
height: MediaQuery
.of(context)
.size
.width *
0.1,
),
TextFormField(
controller: TextEditingController(
text: state.getProfile.lastName),
decoration: InputDecoration(
labelText: 'Last Name'),
keyboardType: TextInputType
.name,
onFieldSubmitted: (
value) {
//Validator
},
validator: (value) {
if (value.isEmpty) {
return 'Required';
}
return null;
},
),
//box styling
SizedBox(
height: MediaQuery
.of(context)
.size
.width *
0.1,
),
SizedBox(
width: double.infinity,
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty
.all(
EdgeInsets.only(
top: 16.0,
bottom: 16.0),),
foregroundColor:
MaterialStateProperty
.all<Color>(
Colors.white),
backgroundColor: MaterialStateProperty
.all<Color>(
Color(
0xFF33138C)),
shape: MaterialStateProperty
.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(
25.0),
side: BorderSide(
color: Color(
0xFF33138C)))),),
onPressed: () =>
_submit(),
child: Text('Save',
style: TextStyle(
fontSize: 16.0
),),
),
),
],
),
),
),
],
),
),
),
);
} else {
return Center(child : CircularProgressIndicator());
}
}
),
SizedBox(height: 150),
],
)),
],
))
],
),
),
),
);
}
}
class ProfileError extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Image.asset('assets/empty-list.png')],
),
Text(
'Error',
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.black87),
),
Padding(
padding: EdgeInsets.only(left: 30.0, right: 30.0),
child: Text(
'After your first order you\'ll be able to view it here',
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w600,
color: Colors.grey,
),
textAlign: TextAlign.center,
),
),
],
),
);
}
}
I used two buttons which make same thing on subcategories screen. On of them in buttom of the screen, other one stays in subcategories part (Empty Card )of the screen, from the bottom button I can add new subcategory but when I pushed to the EmptyCard to add subcategory, adding screen is oppening but when I try to push add button, I took invalid argument(s) error, Can someone help me..
class CategoryModel{
CategoryModel({this.categoryId,this.categoryImagePath,this.categoryName,this.categoryColor,this.subCategory});
final int categoryId;
final SubCategoryModel subCategory;
final Color categoryColor;
final String categoryImagePath;
final String categoryName;
final List<SubCategoryModel> subCategoryModels=[SubCategoryModel(subCategoryId: null)];
}
class SubCategoryModel{
SubCategoryModel({this.subCategoryId,this.subCategoryImagePath,this.subCategoryName, this.categoryColor});
final int subCategoryId;
final Color categoryColor;
final subCategoryImagePath;
final subCategoryName;
class EmptyCard extends StatelessWidget {
EmptyCard({this.where});
final String where;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top:15.0),
child: TextButton(
onPressed: (){
if(where=="homeScreen"){
showModalBottomSheet(
context: context,
builder: (BuildContext context)=> AddMenuScreen(buttonText: "Menü Ekle",route:where),
);
}
else if(where=="subCategoryScreen"){
showModalBottomSheet(
context: context,
builder: (BuildContext context)=> AddMenuScreen(buttonText: "Tarif Ekle",route:where),
);
}
},
child: Container(
height: 180,
width: 180,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.black12.withOpacity(0.1),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.add_circle_outline_outlined,size: 100,color: Colors.grey.shade400,),
],
),
),
),
);
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
title: BorderedText(
child:Text(
categoryModels[widget.categoryId].categoryName,
style: TextStyle(
color: Color(0XFFFFFB00),
fontSize: 30,
fontFamily: "Graduate"
),
),
strokeWidth: 5,
strokeColor: Colors.black,
),
elevation: 5,
backgroundColor: Color(0xFFF2C3D4).withOpacity(1),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.pop(context);
},
iconSize: 40,
color: Color(0xFFA2000B),
),
actions: [
CircleAvatar(
radius: 27,
backgroundColor: Colors.transparent,
backgroundImage: AssetImage("images/cuttedlogo.PNG"),
)
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/logoBGopacity.png"),
fit: BoxFit.cover,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: GridView.builder(
scrollDirection: Axis.vertical,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount:categoryModels[widget.categoryId].subCategoryModels.length,
itemBuilder: (context,index){
if(categoryModels[widget.categoryId].subCategoryModels[index].subCategoryId==null){
return EmptyCard(where: "subCategoryScreen");
}
return SubCategoryCard(subCategoryId:widget.categoryId,subcategoryName: categoryModels[widget.categoryId].subCategoryModels[index].subCategoryName,
subCategoryImagePath: categoryModels[widget.categoryId].subCategoryModels[index].subCategoryImagePath,
subCategoryColor: categoryModels[widget.categoryId].subCategoryModels[index].categoryColor,);
}
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid),
color: kColorTheme7,
borderRadius: BorderRadius.circular(40),
),
child: TextButton(
onPressed: (){
showModalBottomSheet(
context: context,
builder: (BuildContext context)=> AddMenuScreen(categoryId:widget.categoryId,buttonText: "Tarif Ekle", route:"subCategoryScreen"),
);
},
child: BorderedText(
strokeWidth: 5,
strokeColor: Colors.black,
child:Text("Tarif Ekle",style: TextStyle(
color: Colors.white,
fontFamily:'Graduate',
fontSize:30,
),
),
),
),
),
),
],
)
],
),
),
),
);
}
}
class AddMenuScreen extends StatefulWidget {
AddMenuScreen({this.categoryId,this.buttonText, this.route});
final int categoryId;
final String route;
final String buttonText;
static String id="addMenuScreen";
#override
_AddMenuScreenState createState() => _AddMenuScreenState();
}
class _AddMenuScreenState extends State<AddMenuScreen> {
final stickerList= List<String>.generate(23, (index) => "images/sticker$index");
int selectedIndex=-1;
Color _containerForStickersInactiveColor=Colors.white;
Color _containerForStickersActiveColor=Colors.black12;
String chosenImagePath;
String newCategoryName;
int addScreenImageNum;
#override
Widget build(BuildContext context) {
return Material(
child: Container(
color: kColorTheme9,
child: Container(
height: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(40),topLeft: Radius.circular(40)),
),
child:Padding(
padding:EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: kColorTheme2,
borderRadius: BorderRadius.circular(90)
),
child: TextField(
style: TextStyle(
color: Colors.black,
fontFamily:"Graduate",
fontSize: 20,
),
textAlign: TextAlign.center,
onChanged: (value){
newCategoryName=value;
},
decoration: InputDecoration(
border:OutlineInputBorder(
borderRadius: BorderRadius.circular(90),
borderSide: BorderSide(
color: Colors.teal,
),
),
hintText: "Menü ismi belirleyin",
hintStyle: TextStyle(
color: Colors.black.withOpacity(0.2),
fontFamily: "Graduate",
),
),
),
),
SizedBox(height: 20,),
Text(" Yana kadırarak menünüz icin bir resim secin",textAlign: TextAlign.center,
style: TextStyle(fontFamily: "Graduate", fontSize: 12),),
SizedBox(height: 20,),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: stickerList.length,
itemBuilder: (context,index){
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: index == selectedIndex ?
_containerForStickersActiveColor :
_containerForStickersInactiveColor,
),
child:TextButton(
child: Image(
image: AssetImage("images/sticker$index.png"),
),
onPressed: (){
setState(() {
selectedIndex = index;
});
},
),
);
}
),
),
SizedBox(height: 20,),
Container(
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid),
color: kColorTheme7,
borderRadius: BorderRadius.circular(90),
),
child: TextButton(
onPressed: (){
if(widget.route=="homeScreen"){
Navigator.pop(context, ModalRoute.withName(HomeScreen.id));
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>HomeScreen(newCategoryName: newCategoryName,
newCategoryImagePath: "images/sticker$selectedIndex.png")));
}
else if(widget.route=="subCategoryScreen"){
Navigator.pop(context, ModalRoute.withName(SubCategoriesScreen.id));
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>SubCategoriesScreen(categoryId: widget.categoryId,subCategoryName: newCategoryName,
subCategoryImagePath:"images/sticker$selectedIndex.png" )));
}
},
child: Text(widget.buttonText, style: TextStyle(fontSize: 20, color: Colors.white,
fontFamily: "Graduate", fontWeight: FontWeight.bold),),
),
),
],
),
),
),
),
);
}
}
In flutter, I want to make an application that scans qr code and display the qr text.
I have two buttons, which are done, scan again.
And how to put that 2 button, bottom of that scan area. If i try to put that button inside expanded layer, it looks all red
Here is the code & screenshot.
How can i solve this ?
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:qr_code_scanner/qr_scanner_overlay_shape.dart';
void main() => runApp(MaterialApp(home: QRSCAN()));
const flash_on = "FLASH ON";
const flash_off = "FLASH OFF";
const front_camera = "FRONT CAMERA";
const back_camera = "BACK CAMERA";
class QRSCAN extends StatefulWidget {
const QRSCAN({
Key key,
}) : super(key: key);
#override
State<StatefulWidget> createState() => _QRSCANState();
}
class _QRSCANState extends State<QRSCAN> {
bool Done_Button = false;
var qrText = "";
QRViewController controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.blueAccent),
onPressed: () {
Navigator.pop(context);
controller?.pauseCamera();
},
),
elevation: 0.0,
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(
icon: Icon(Icons.help_outline, color: Colors.grey,),
onPressed: () {},
),
],
),
body: Column(
children: <Widget>[
Expanded(
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.blueAccent,
borderRadius: 10,
borderLength: 130,
borderWidth: 5,
overlayColor: Color(0xff010040),
),
),
flex: 4,
),
Expanded(
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text("$qrText", style: TextStyle(color: Colors.black,),),
InkWell(
onTap: () async {
Navigator.pop(context);
},
child: Container(
width: 100.0,
height: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(colors: [
Color(0xFF1E75BB),
Color(0xFF1EEABB),
])),
child: Center(
child: Text(
'Done',
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize: 12.0,
fontWeight: FontWeight.bold,
fontFamily: 'Play',
),
),
),
),
),
SizedBox(
height: 25,
),
InkWell(
onTap: () async {
setState(() {
qrText = "";
controller?.resumeCamera();
Done_Button = false;
});
},
child: Container(
width: 100.0,
height: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(colors: [
Color(0xFF1E75BB),
Color(0xFF1EEABB),
])),
child: Center(
child: Text(
'Again',
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize: 12.0,
fontWeight: FontWeight.bold,
fontFamily: 'Play',
),
),
),
),
),
],
),
),
flex: 1,
),
],
),
);
}
_isFlashOn(String current) {
return flash_on == current;
}
_isBackCamera(String current) {
return back_camera == current;
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
setState(() {
qrText = scanData;
controller?.pauseCamera();
Done_Button = true;
});
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
}
you can refactor your code as follows
` Column(children: <Widget>[
/* QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.blueAccent,
borderRadius: 10,
borderLength: 130,
borderWidth: 5,
overlayColor: Color(0xff010040),
),
),*/
SizedBox(height:5),
Center(
child: Container(height: 100, color: Colors.white, width: 100),
),
Text(
"$qrText",
style: TextStyle(
color: Colors.black,
),
),
InkWell(
onTap: () async {
Navigator.pop(context);
},
child: Container(
width: 100.0,
height: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(colors: [
Color(0xFF1E75BB),
Color(0xFF1EEABB),
])),
child: Center(
child: Text(
'Done',
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize: 12.0,
fontWeight: FontWeight.bold,
fontFamily: 'Play',
),
),
),
),
),
SizedBox(
height: 25,
),
InkWell(
onTap: () async {
setState(() {
qrText = "";
// controller?.resumeCamera();
// Done_Button = false;
});
},
child: Container(
width: 100.0,
height: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(colors: [
Color(0xFF1E75BB),
Color(0xFF1EEABB),
])),
child: Center(
child: Text(
'Again',
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize: 12.0,
fontWeight: FontWeight.bold,
fontFamily: 'Play',
),
),
),
),
),
]),
);`