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! :)
Related
I have a question about updating Android Emulator after pressing on an icon using setState()
this is my code:
import 'package:flutter/material.dart';
void main() {
return runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
title: Text('Dicee'),
backgroundColor: Colors.red,
),
body: DicePage(),
),
),
);
}
class DicePage extends StatefulWidget {
#override
_DicePageState createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
#override
Widget build(BuildContext context) {
int leftDiceNumber = 1;
return Center(
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
setState(() {
leftDiceNumber = 5;
});
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: TextButton(
onPressed: () {
print('Right button got pressed.');
},
child: Image.asset('images/dice2.png'),
),
),
],
),
);
}
}
and I tried even multiple choices that I found in Stackoverflow , but nothing it's working...
this.setState(() {
leftDiceNumber = 5;
});
WidgetsBinding.instance.addPostFrameCallback((_) => setState(...));
insted of just setState() and didn't work
I want to change the value of leftDiceNumber = 5 when I click on the picture
the initialised value for leftDiceNumber is 1
Put the variable outside the build method.leftDiceNumber, else it will reset on every build.
class DicePage extends StatefulWidget {
#override
_DicePageState createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
int leftDiceNumber = 1; //here
#override
Widget build(BuildContext context) {
return Center(
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
setState(() {
leftDiceNumber = 5;
});
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: TextButton(
onPressed: () {
print('Right button got pressed.');
},
child: Image.asset('images/dice2.png'),
),
),
],
),
);
}
}
I want to display notifications that are being processed by a provider on an open gRPC stream. This is handled by notificationProvider.dart:
if (notification.type == 0) {
showOverlayNotification(notification);
} else {
notificationList.add(notification);
notifyListeners();
}
showOverlayNotification() then displays custom notification Widget OverlayNotification() on top of the current screen that user is in, like:
showOverlayNotification() async {
OverlayState? overlayState = Overlay.of(**context**);
OverlayEntry overlayEntry = OverlayEntry(builder: (context) {
return Positioned.fill(child: OverlayNotification());
});
overlayState?.insert(overlayEntry);
}
Now the problem is that I don't know how to get to the current context the user is in?
Android was pretty straightforward with this, but I can't seem to find this in Flutter..
How do I display overlay widget to a current context?
Do I have to keep track of it in a global variable in the end?
Can I find it through NamedRoutes?
can do something like this, fyi if you don't want to use navigator to pop current view you can create a navigator key as shown here
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: MyWidget(),
),
),
);
}
}
_buildPopupMessage(BuildContext context){
return Center(
child: IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return FittedBox(
fit: BoxFit.scaleDown,
child: AlertDialog(
title: Text(
'title text',
textAlign: TextAlign.center,
),
content: Text('message text here',
textAlign: TextAlign.center),
actions: <Widget>[
TextButton(
onPressed: () {
debugPrint('closed pressed');
Navigator.pop(context);
},
child: Text('close'),
)
],
),
);
},
);
},
icon: Icon(
Icons.live_help,
),
),
);
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body:_buildPopupMessage(context),
);
}
}
I'm new to Flutter. I'm trying to build a basic dice app with a button. When the button is clicked, the displayed text gets updated with a random number.
import 'package:flutter/material.dart';
import 'dart:math';
int dice = 0;
void main() {
int dice = 0;
runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.white70,
appBar: AppBar(
title: const Text('Quick Dice'),
backgroundColor: Colors.blueGrey,
),
body: Center(
child: MaterialButton(
onPressed: () {
rollDice();
},
child: new Text('$dice'),
),
),
),
),
);
}
void rollDice(){
dice = Random().nextInt(6) + 1;
print('In Roll Dice()');
print('$dice');
}
When the button is clicked, I can see that the function rollDice() is being called and the value of $dice is being updated but on the screen, the value never gets updated.
Is there something I'm missing? Should the child text element be refreshed somehow to to show the new value on button press?
Do like this ( StatefulWidget ) :
void main(){
runApp(MaterialApp(
home: UpdateScreen(),
));
}
class UpdateScreen extends StatefulWidget{
#override
UpdateScreenState createState() => UpdateScreenState();
}
class UpdateScreenState extends State<UpdateScreen>{
int dice = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white70,
appBar: AppBar(
title: const Text('Quick Dice'),
backgroundColor: Colors.blueGrey,
),
body: Center(
child: MaterialButton(
onPressed: () {
rollDice();
},
child: new Text('$dice'),
),
),
);
}
void rollDice(){
setState(() {
dice = Random().nextInt(6) + 1;
print('In Roll Dice()');
print('$dice');
});
}
}
Try below code hope its helpful to you.
Refer Random here
and use dart.math library here
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MaterialApp(
home: DiceApp(),
));
}
class DiceApp extends StatefulWidget {
#override
DiceAppState createState() => DiceAppState();
}
var randomNo = new Random();
var dice = randomNo.nextInt(6) + 1;
class DiceAppState extends State<DiceApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dice App'),
),
body: Center(
child: MaterialButton(
color: Colors.blue,
onPressed: () {
setState(() {
dice = randomNo.nextInt(6) + 1;
});
},
child: Text(
dice.toString(),
),
),
),
);
}
}
Your result screen-> |
For updating your data on screen you have to use state management like provider, Getx , block etc. Or you can use the setState method in your rollDice() function then the the widget will rebuild and your data will be updated. Something like this--
void rollDice(){
setState(() {
dice = Random().nextInt(6) + 1
});
print('In Roll Dice()');
print('$dice');
}
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);
});
}
I have following route in my app:
Main.dart ---> SplashScreen.dart ---> DetailsPage.dart
Main.dart
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => FontSizeHandler()),
],
child: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SplashScreen(),
);
}
}
From SplashScreen.dart I move to DetailsPage.dart using Navigator.pushAndRemoveUntil i.e
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => DetailsPage()), (route) => false);
Now in Details page on App Bar there is icon and on press of which I want to change the font using FontSizeHandler
DetailsPage.dart
class DetailsPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.arrow_upward),
onPressed: () {
context.read<FontSizeHandler>().increaseFont();
},
),
IconButton(
onPressed: () {
context.read<FontSizeHandler>().decreaseFont();
},
icon: Icon(Icons.arrow_downward),
),
],
title: Text(
"DetailsPage",
style: GoogleFonts.roboto(),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Card(
child: Container(
padding: EdgeInsets.fromLTRB(5, 5, 5, 15),
child: AutoSizeText(
"MyTexts",
textAlign: TextAlign.justify,
style: GoogleFonts.openSans(
fontSize:
context.watch<FontSizeHandler>().fontSize.toDouble(),
),
),
),
),
),
),
);
}
}
So the problem here is I am getting this error message
Could not find the correct Provider This likely
happens because you used a BuildContext that does not include the
provider
Is this error is due to I used Navigator.pushAndRemoveUntil?
Though I have ChangeNotifierProvider at top of hierarchy why is it throwing error?
How to solve this?
FontSizeHandler.dart
class FontSizeHandler with ChangeNotifier {
int fontSize = 15;
void increaseFont() {
fontSize = fontSize + 2;
notifyListeners();
}
void decreaseFont() {
fontSize = fontSize - 2;
notifyListeners();
}
}
Solved: The Problem Was With Importing Wrong ChangeNotifier class. Never Trust autoimport again
Updated Answer
For reference, the issue was caused by an erroneous import as below:
import 'file:///.../fontchangehandler.dart'; // import 'package:.../fontchangehandler.dart';
Original Answer
Unfortunately I was unable to reproduce the error that you are experiencing using the provided code. If you could provide the rest of the code from the DetailsPage class then that might help to further diagnose the error. I was able to get the example below working which hopefully you might find useful:
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<FontSizeHandler>(
create: (context) {
return FontSizeHandler();
},
),
],
child: MyApp(),
),
);
}
class FontSizeHandler extends ChangeNotifier {
int _fontSize = 15;
int get fontSize => _fontSize;
void increaseFont() {
_fontSize = _fontSize + 2;
notifyListeners();
}
void decreaseFont() {
_fontSize = _fontSize - 2;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SplashScreen(),
);
}
}
class SplashScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () async {
await Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) {
return DetailsPage();
},
),
(route) => false,
);
},
child: Text('GO TO DETAILS'),
),
),
);
}
}
class DetailsPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.arrow_upward),
onPressed: () {
context.read<FontSizeHandler>().increaseFont();
},
),
IconButton(
onPressed: () {
context.read<FontSizeHandler>().decreaseFont();
},
icon: Icon(Icons.arrow_downward),
),
],
title: Text(
"DetailsPage",
style: GoogleFonts.roboto(),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Card(
child: Container(
padding: EdgeInsets.fromLTRB(5, 5, 5, 15),
child: AutoSizeText(
"MyTexts",
textAlign: TextAlign.justify,
style: GoogleFonts.openSans(
fontSize: context.watch<FontSizeHandler>().fontSize.toDouble(),
),
),
),
),
),
),
);
}
}