I have an App made with flutter that when a button is pressed it increments a counter by 1. I would like to make the counter go to 10 and then simply start at 0 again. Is this possible?
this is code for the onPressed:
RaisedButton(
splashColor: Colors.blueAccent[700],
child: Text(
'+ Hit',
style: TextStyle(color: Colors.black),
),
color: Colors.lightBlue[100],
onPressed: _incrementCounter,
),
and the _incrementCounter section of code: (I am storing the value in shared prefs)
_incrementCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
counter = (prefs.getInt('counter') ?? 0) + 1;
prefs.setInt('counter', counter);
});
}
How do i add the condition to start again when reaching 10??
Thanks to all
Add a condition on the onTap function of the button, where when counter > 10 then counter = 0
Do something like this in your function which is triggered on button click
void _incrementCounter() {
setState(() {
if (_counter == 10) {
_counter = 0;
} else {
_counter++;
}
});
}
_counter represents the variable which is holding count value
Sure it is.
you have to use an if satement which sets the counter back to zero once it has reached 10.
Run on DartPad
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
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;
void _incrementCounter() {
setState(() {
// Your IF statement wgich defines when the counter goes back to zero
if(_counter>=10) {
_counter=0;
} else {
_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),
),
);
}
}
many thanks. This is now solved, apologies taken so long to post answer but have had to isolate (without laptop :( ),
Here is the code that works. Thanks again to the above contributions. You really helped
_incrementCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
if (counter >= 10) {
counter = 1;
} else {
prefs.setInt('counter', counter++);
}
prefs.setInt('counter', counter);
});
}
Related
I want to see a the value of a counter in a flutter UI when the counter is updated asynchronously.
Staring from the sample flutter project, I would expect the below would make it, but only the final value is displayed. How can I achieve to see the numbers changing from 1 to 100000?
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() async {
for(int i=0; i<100000; ++i) {
setState(() {
_counter++;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
I think the issue is just that your loop is running too fast to show the intermediate values. Slowing the loop down with Future.delayed() should let you see what you want.
void _incrementCounter() async {
for(int i=0; i<100000; ++i) {
await Future.delayed(Duration(seconds: 1));
setState(() {
_counter++;
});
}
}
to see the numbers changing from 1 to 100000 You can use Timer.periodic.
Creating state level timer variable to have control on running state.
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Timer? _timer;
void _incrementCounter() async {
const delay = Duration(milliseconds: 100); // controll update speed
const numberLimit = 100000;
_timer = Timer.periodic(delay, (timer) {
if (_counter < numberLimit) {
setState(() {
_counter++;
});
} else {
timer.cancel();
}
});
}
void _reset() {
setState(() {
_counter = 0;
});
_timer?.cancel();
}
#override
void dispose() {
_timer?.cancel();
super.dispose();
}
You can find more about dart-async-library and Timer.periodic on flutter.dev.
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late Timer _timer;
int _start = 0;
void startTimer() {
const oneSec = const Duration(seconds: 1);
_timer = new Timer.periodic(
oneSec,
(Timer timer) => setState(() {
if (_start > 100000) {
timer.cancel();
} else {
_start = _start + 1;
}
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_start',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: startTimer,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Hey you can use ValueListenableBuilder to notify you state instead of calling setState as it will rebuild whole ui. Read here in more details about ValueListenableBuilder
Below is sample code -
class _MyHomePageState extends State<MyHomePage> {
Timer? _timer;
ValueNotifier _valueNotifier = ValueNotifier(0);
#override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: _valueNotifier,
builder: (context, value, child) {
return Text(value.toString());
},
);
}
void _incrementCounter() async {
const delay = Duration(milliseconds: 100); // controll update speed
const numberLimit = 100000;
_timer = Timer.periodic(delay, (timer) {
if (_valueNotifier.value < numberLimit) {
_valueNotifier.value++;
} else {
timer.cancel();
}
});
}
void _reset() {
_valueNotifier.value = 0;
_timer?.cancel();
}
#override
void dispose() {
_timer?.cancel();
_valueNotifier.dispose();
super.dispose();
}
I'm trying to learn flutter and my first 'APP' is a counter. The counter was working, but I would like to increment it and put a button to reset the count. Here's my code:
'''
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
theme: ThemeData(primarySwatch: Colors.purple), home: HomePage()));
}
class HomePage extends StatefulWidget {
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var count = 0;
void reset() {
count = 0;
setState(() {});
}
void increment() {
count++;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Meu Primeiro APP!"),
),
body: Center(
child: Text(
"Contador\n$count",
textAlign: TextAlign.center,
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
increment();
},
),
);
}
}
'''
I've done searches on the internet and still haven't found the solution to this problem, which apparently is simple to solve.
First of all you need to create a new button with that functionality of resetting your counter variable. Wrap your center widget with a column and add a new button like this:
Column(
children: [
Center(
child: Text(
"Contador\n$count",
textAlign: TextAlign.center,
),
),
ElevatedButton(
child: const Text("Reset Counter"),
onPressed: () {
setState(() {
count = 0;
});
},
),
],
),
In order to see the counter updating on your screen you have to call the increment method inside of setState() so the framework schedules a rebuild!
void increment() {
setState(() {
count++;
});
}
I suggest you do some tutorials on the official flutter site to get started with the core fundamentals of flutter - happy coding! :)
I want to make the initial value of the TextFormField equal to the counter variable. The counter is maintained between app restarts, but when I restart the app, the initial value of the text field is always 0.
Is there a better way of doing that?
(I'm new to programming, sorry if it's a dumb question)
Here's the code I used.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Shared preferences demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Shared preferences demo'),
);
}
}
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;
#override
void initState() {
super.initState();
_loadCounter();
}
//Loading counter value on start
_loadCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_counter = (prefs.getInt('counter') ?? 0);
});
}
//Incrementing counter after click
_incrementCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_counter = (prefs.getInt('counter') ?? 0) + 1;
prefs.setInt('counter', _counter);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
TextFormField(
initialValue: '$_counter',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Try adding a controller for TextFormField and update the value after getting it from SharedPreferences.
Something like this.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Shared preferences demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Shared preferences demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
final myController = TextEditingController();
#override
void dispose() {
myController.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
_loadCounter();
}
_loadCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_counter = (prefs.getInt('counter') ?? 0);
myController.text = _counter.toString();
});
}
_incrementCounter() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_counter = (prefs.getInt('counter') ?? 0) + 1;
prefs.setInt('counter', _counter);
myController.text = _counter.toString();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
TextFormField(
controller: myController,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Hope this solves your issue.
How can I implement a triple-click button in flutter?
On triple-click, the button will store an entry in Firebase database.
Its pretty easy. You can use a GestureDetector() to check for the number of taps then you can provide your logic if there are 3 taps.
GestureDetector(
onTap: () {
int now = DateTime.now().millisecondsSinceEpoch;
if (now - lastTap < 1000) {
print("Consecutive tap");
consecutiveTaps ++;
print("taps = " + consecutiveTaps.toString());
if (consecutiveTaps == 3){
// Do something
}
} else {
consecutiveTaps = 0;
}
lastTap = now;
},
child: ...
)
Implementing "triple click" button in flutter might not be possible. But, if you really want to make it work ASAP then a simple method could be to maintain a counter for the number of clicks done. Once the count reaches 3, you need to add your entry to Firestore.
I have modified the code from the counter app boilerplate of flutter.
Hope you have cloud_firestore in your pubspec.yaml file. If not then add it and put the services.json as well in the app folder of android or respective directory of ios.
cloud_firestore: ^0.13.4+1
So, now you can have a look at the code that I am using.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
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;
_incrementCounter() {
setState(() {
_counter++;
});
if (_counter == 3) {
Firestore.instance
.collection('/sampleData')
.add({'data': "data"}).catchError((e) {
print(e);
});
setState(() {
_counter = 0;
});
}
}
#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.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
I have edited the _incrementCounter function. I added a conditional statement to check the _counter if it is 3 or not. Then, I am adding the Firestore entry. Later on, the most important bit is to set the _counter as 0 so that the next time the user presses the button 3 times, then the code will work accordingly. You can customize it according to your needs.
But remember, triple clicks have not been yet invented in flutter and this is just a work-around solution and don't use it for Real-life Development applications as this would be a very bad practice.
I am new to Flutter, and trying to understand how to to perform a series of actions based on a state of the widget.
I have a VERY basic app, based on the default new Flutter app with the clicks counter. I'd like that when the counter hits 10, the counter text highlights in red for 500ms (showing '10') and then the counter gets reset back to 0 and the text goes back to black (showing '0').
I was able to change the color to red when _counter==10, but unsure how to change it back to black and reset the counter after a set period of time. I'd also want to make the button "unclickable" during the 500ms.
It's simple just follow the code below,
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
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;
bool isButtonEnabled = true;
Future<void> _incrementCounter() async {
_counter++;
if (_counter == 10) {
setState(() {
isButtonEnabled = false;
});
await Future.delayed(Duration(milliseconds: 500));
setState(() {
_counter = 0;
isButtonEnabled = true;
});
} else {
setState(() {});
}
}
#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:
TextStyle(color: isButtonEnabled ? Colors.black : Colors.red),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: isButtonEnabled ? _incrementCounter : null,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
You're done.