Stopwatch don't decrease time - flutter

I'm trying to make a timer that can be instantiated by any class, but I'm having problems with the TimerWidget class, since its value does not reduce in startTimer(). When called, the class has the same attributes as the TimerWidget class, and as described in the parameter, the timer starts counting with the required value. The errors say that the operator '<' and '-' do not belong to the type Time.
Any suggestions? Tips? I'm new to flutter.
import 'package:flutter/material.dart';
import 'dart:async';
class TimerWidget extends StatefulWidget {
final int hours; // 1 hour:
final int minutes; // 60
final int seconds; // 3.600
final int millisecond; // 3.600.000
final int microsecond; // 3.600.000.000
final int nanosecond; // 3.600.000.000.000
TimerWidget({
this.hours,
this.minutes,
u/required this.seconds,
this.millisecond,
this.microsecond,
this.nanosecond,
});
#override
_TimerWidgetState createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
Timer _timer;
var start = TimerWidget(seconds: 30);
void startTimer() {
const oneSec = const Duration(seconds: 1);
_timer = new Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (start < 1) {
timer.cancel();
} else {
start = start - 1;
}
},
),
);
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
startTimer();
},
child: Text("start"),
),
Text("$start")
],
),
);
}
}

You can copy paste run full code below
You can use var start = 30; not var start = TimerWidget(seconds: 30);
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
class TimerWidget extends StatefulWidget {
final int hours; // 1 hour:
final int minutes; // 60
final int seconds; // 3.600
final int millisecond; // 3.600.000
final int microsecond; // 3.600.000.000
final int nanosecond; // 3.600.000.000.000
TimerWidget({
this.hours,
this.minutes,
#required this.seconds,
this.millisecond,
this.microsecond,
this.nanosecond,
});
#override
_TimerWidgetState createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
Timer _timer;
var start = 30;
void startTimer() {
const oneSec = const Duration(seconds: 1);
_timer = new Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (start < 1) {
timer.cancel();
} else {
start = start - 1;
}
},
),
);
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text("demo")),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
startTimer();
},
child: Text("start"),
),
Text("$start")
],
),
),
);
}
}
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: TimerWidget(seconds: 30),
);
}
}
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),
),
);
}
}

Related

Flutter : I want to reflect timer variables in the Mac OS system tray

I use a package called system_tray from flutte Mac OS.
I am trying to create a simple countdown timer and want to reflect the timer value in the system tray, but it is not reflected. How can I get it reflected?
This is all code.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:system_tray/system_tray.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({
super.key,
});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Timer? countdownTimer;
Duration myDuration = Duration(hours: 80);
var hours;
var minutes;
var seconds;
Future<void> initSystemTray() async {
final SystemTray systemTray = SystemTray();
await systemTray.initSystemTray(
title: '$hours:$minutes:$seconds',
iconPath: '',
);
await Future.delayed(const Duration(seconds: 1));
print('success');
setState(() {});
initSystemTray();
}
void startTimer() {
countdownTimer =
Timer.periodic(Duration(seconds: 1), (_) => setCountDown());
}
void pauseTimer() {
setState(() => countdownTimer!.cancel());
}
void resetTimer() {
pauseTimer();
setState(() => myDuration = Duration(hours: 80));
}
void setCountDown() {
final reduceSecondsBy = 1;
setState(() {
final seconds = myDuration.inSeconds - reduceSecondsBy;
if (seconds < 0) {
countdownTimer!.cancel();
} else {
myDuration = Duration(seconds: seconds);
}
});
}
#override
void initState() {
initSystemTray();
super.initState();
}
#override
Widget build(BuildContext context) {
String strDigits(int n) => n.toString().padLeft(2, '0');
hours = strDigits(myDuration.inHours);
minutes = strDigits(myDuration.inMinutes.remainder(60));
seconds = strDigits(myDuration.inSeconds.remainder(60));
return Scaffold(
appBar: AppBar(),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(onPressed: startTimer, icon: Icon(Icons.play_arrow)),
IconButton(
onPressed: () {
if (countdownTimer == null || countdownTimer!.isActive) {
pauseTimer();
}
},
icon: Icon(Icons.pause)),
Text(
'$hours:$minutes:$seconds',
style: TextStyle(fontSize: 60),
),
IconButton(
onPressed: () {
resetTimer();
},
icon: Icon(Icons.restart_alt)),
// Step 11
],
),
),
);
}
}
Recursive function is executed but null is displayed
How do I get the hours minutes seconds variable reflected in the system tray?

Flutter: Update the UI with value from an async function

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();
}

Need Help in getting respective value from a custom widget

I am a noob in flutter and i need help with this. So I made this counter widget where you can increase and decrease the counter value with button, and called that widget two times in my root widget. now I want to get respective counter value of those counter widget separately for each time I call my counter widget. How do I achieve that.
this is my main.dart file
class _MyHomePageState extends State<MyHomePage> {
int count;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CounterContainer(count, ValueKey(1)),
Text('first counter : ${CounterContainer(count, ValueKey(1)).count}'),
CounterContainer(count, ValueKey(2)),
Text('second counter : ${CounterContainer(count, ValueKey(2)).count}'),
],
),
),
);
}
}
this is my Counter_widget
class CounterContainer extends StatefulWidget {
int count;
CounterContainer(this.count, ValueKey<int> valueKey);
#override
_CounterContainerState createState() => _CounterContainerState();
}
class _CounterContainerState extends State<CounterContainer> {
int _counter = 0;
void _incrementCounter() {
setState(() {
widget.count = ++_counter;
print('------------>${widget.count}');
});
}
void _decrementCounter() {
setState(() {
if (_counter > 0) {
widget.count = --_counter;
print('------------>${widget.count}');
}
});
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
FlatButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
Text('$_counter'),
FlatButton(
onPressed: _decrementCounter,
child: Icon(Icons.remove),
),
],
);
}
}
You can copy paste run full code below
You can define two counters counter1 and counter2 and pass callback to do refresh
working demo
code snippet
void _incrementCounter() {
setState(() {
...
});
widget.callback();
}
void _decrementCounter() {
setState(() {
...
});
widget.callback();
}
...
CounterContainer counter1;
CounterContainer counter2;
void refresh() {
print("refresh");
setState(() {});
}
#override
void initState() {
counter1 = CounterContainer(count, ValueKey(1), refresh);
counter2 = CounterContainer(count, ValueKey(2), refresh);
super.initState();
}
...
children: <Widget>[
counter1,
Text('first counter : ${counter1.count}'),
counter2,
Text('second counter : ${counter2.count}'),
],
full code
import 'package:flutter/material.dart';
class CounterContainer extends StatefulWidget {
int count;
VoidCallback callback;
CounterContainer(this.count, ValueKey<int> valueKey, this.callback);
#override
_CounterContainerState createState() => _CounterContainerState();
}
class _CounterContainerState extends State<CounterContainer> {
int _counter = 0;
void _incrementCounter() {
setState(() {
widget.count = ++_counter;
print('------------>${widget.count}');
});
widget.callback();
}
void _decrementCounter() {
setState(() {
if (_counter > 0) {
widget.count = --_counter;
print('------------>${widget.count}');
}
});
widget.callback();
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
FlatButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
Text('$_counter'),
FlatButton(
onPressed: _decrementCounter,
child: Icon(Icons.remove),
),
],
);
}
}
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 count;
CounterContainer counter1;
CounterContainer counter2;
void refresh() {
print("refresh");
setState(() {});
}
#override
void initState() {
counter1 = CounterContainer(count, ValueKey(1), refresh);
counter2 = CounterContainer(count, ValueKey(2), refresh);
super.initState();
}
#override
Widget build(BuildContext context) {
print('${counter1.count}');
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
counter1,
Text('first counter : ${counter1.count}'),
counter2,
Text('second counter : ${counter2.count}'),
],
),
),
);
}
}

How to make a counter that multiples in the background with async

I'm trying to make a clicker-like app to test myself. Everything was perfect until I came to async thing. The thing I want to do is a program that multiplies itself by it's house numbers. Like, user if user has 2 home, user should earn 2 points per second. I read the original documentation of dart and made it from copying there.
Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:async/async.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: 'Zikirmatik'),
);
}
}
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;
int _max = 0;
int _ev = 0;
int _toplanan = 0;
void _incrementCounter() {// Eklemeler sürekli tekrar çağrıldığı için bunları ayrı bir voide almamız gerek
setState(() { //Tekrar çağrılmasını sağlayan komut
_counter++;
});
}
void _decreaseCounter(){
setState(() {
_counter--;
});
}
void _resetCounter(){
setState(() {
_counter = 0;
});
}
void _evArttiran(){
setState(() {
_ev++;
});
}
void _otoArttiran(){
setState(() {
_toplanan = _ev * 1;
});
}
#override
Widget build(BuildContext context) {
if(_counter > _max){ //Yüksek skor if'i
_max = _counter;
}
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Skor:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1, // Anlık skoru kalın göstern
),
Text(
'Yüksek Skor:',
),
Text(
'$_max',
),
Text(
'Ev Sayısı:',
),
Text(
'$_ev',
),
OutlineButton( // Büyük button
onPressed: () => _incrementCounter(), // Ayrı bi void yazmamak için fat işaret kullanıyoruz
child: Container(
width: 1000, // Ayarlamazsanız küçük oluyor
height: 500,
child: Icon(Icons.add, size:100)
)
)
],
),
),
floatingActionButton: Row( //Yan yana düğme yazmak için Row gerek
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton( //Düz ufak butonlar
onPressed: _evArttiran,
child: Icon(Icons.home),
),
],
)
);
}
main() async{
Timer(Duration(seconds: 1), () {
_otoArttiran;
debugPrint(_toplanan.toString());
_counter += _toplanan;
});
}
}
You need to create a periodic timer and don't forget to put () after _otoArttiran inside the timer callback:
main() async{
Timer.periodic(Duration(seconds: 1), (_) {
_otoArttiran();
debugPrint(_toplanan.toString());
_counter += _toplanan;
});
}
You need to call this function in order for the timer to start working, so let's add initState method to your _MyHomePageState:
#override void initState() {
super.initState();
main();
}
Done!
So here is the complete code:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new TheApp());
class TheApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Zikirmatik'),
);
}
}
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;
int _max = 0;
int _ev = 0;
int _toplanan = 0;
#override void initState() {
super.initState();
main();
}
void _incrementCounter() {// Eklemeler sürekli tekrar çağrıldığı için bunları ayrı bir voide almamız gerek
setState(() { //Tekrar çağrılmasını sağlayan komut
_counter++;
});
}
void _decreaseCounter(){
setState(() {
_counter--;
});
}
void _resetCounter(){
setState(() {
_counter = 0;
});
}
void _evArttiran(){
setState(() {
_ev++;
});
}
void _otoArttiran(){
setState(() {
_toplanan = _ev * 1;
});
}
#override
Widget build(BuildContext context) {
if(_counter > _max){ //Yüksek skor if'i
_max = _counter;
}
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Skor:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1, // Anlık skoru kalın göstern
),
Text(
'Yüksek Skor:',
),
Text(
'$_max',
),
Text(
'Ev Sayısı:',
),
Text(
'$_ev',
),
OutlineButton( // Büyük button
onPressed: () => _incrementCounter(), // Ayrı bi void yazmamak için fat işaret kullanıyoruz
child: Container(
width: 1000, // Ayarlamazsanız küçük oluyor
height: 500,
child: Icon(Icons.add, size:100)
)
)
],
),
),
floatingActionButton: Row( //Yan yana düğme yazmak için Row gerek
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton( //Düz ufak butonlar
onPressed: _evArttiran,
child: Icon(Icons.home),
),
],
)
);
}
main() async{
Timer.periodic(Duration(seconds: 1), (_) {
_otoArttiran();
debugPrint(_toplanan.toString());
_counter += _toplanan;
});
}
}
I'm not sure if i understood correctly but maybe you can to try something like this:
(inside _MyHomePageState)
#override
void initState() {
super.initState();
Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_counter = _counter + _ev;
});
});
}

How to recall method initState each time that I navigate to a specific tab in flutter?

I'm doing a flutter app with Cupertino, I'm trying to figure out how to recall method initState each time that I navigate to this tab (MapPage).
This method initState() calls other mehtod "initPlatformState()" who asks for the permission location and makes a request to an API, with this result I build a marker per each object's result and show them on the map.
Here is the code of the map page.
https://gist.github.com/GreyHat147/3ea92f4e962218893b84af667452b087
This is the ui.
For CupertinoTabBar you can do as below where create instance of state class and the without creating it again called it only on tap:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
MyHome myHome = new MyHome();
MyNearMe myNearMe = new MyNearMe();
MyMap myMap = new MyMap();
MyNotifications myNotifications = new MyNotifications();
MyWallet myWallet = new MyWallet();
MyHomeState myHomeState = MyHomeState();
MyNearMeState myNearMeState = MyNearMeState();
MyMapState myMapState = MyMapState();
MyNotificationsState myNotificationsState = MyNotificationsState();
MyWalletState myWalletState = MyWalletState();
int indexPrevValue = 0;
class TabBarPage extends StatefulWidget {
TabBarPage({Key key, this.userId})
: super(key: key);
final String userId;
#override
_TabBarPage createState() => new _TabBarPage();
}
class _TabBarPage extends State<TabBarPage> {
_TabBarPage({Key key, this.userId});
final String userId;
void _onTap(int value) {
print('Value => $value');
if(value == 0){
myHomeState.initState();
}
else if(value == 1){
myNearMeState.initState();
}
else if(value == 2){
myMapState.initState();
}
else if(value == 3){
myNotificationsState.initState();
}
else if(value == 4){
myWalletState.initState();
}
indexPrevValue = value;
}
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
onTap: _onTap,
activeColor: new Color.fromRGBO(148, 3, 123, 1.0),
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(
title: new Text('Home'),
icon: new Icon(
Icons.home,
size: 22,
),
),
new BottomNavigationBarItem(
title: new Text('Near me'),
icon: new Icon(
Icons.location_on,
size: 22,
),
),
new BottomNavigationBarItem(
icon: new Icon(
Icons.map,
size: 22,
),
title: new Text('Map')
),
new BottomNavigationBarItem(
title: new Text('Notifications'),
icon: new Icon(
Icons.notifications,
size: 22,
)
),
new BottomNavigationBarItem(
title: new Text('Wallet'),
icon: new Icon(
Icons.account_balance_wallet,
size: 22,
)
),
],
),
tabBuilder: (BuildContext context, int index) {
switch (index) {
case 0:
return CupertinoTabView(
builder: (BuildContext context) {
if(myHomeState == null){
myHomeState = myHome.createState();
}
return myHome.createState().build(context);
},
);
break;
case 1:
return CupertinoTabView(
builder: (BuildContext context) {
if(myNearMeState == null){
myNearMeState = myNearMe.createState();
}
return myNearMe.createState().build(context);
},
);
break;
case 2:
return CupertinoTabView(
builder: (BuildContext context) {
if(myMapState == null){
myMapState = myMap.createState();
}
return myMap.createState().build(context);
},
);
break;
case 3:
return CupertinoTabView(
builder: (BuildContext context) {
if(myNotificationsState == null){
myNotificationsState = myNotifications.createState();
}
return myNotifications.createState().build(context);
},
);
break;
case 4:
return CupertinoTabView(
builder: (BuildContext context) {
if(myWalletState == null){
myWalletState = myWallet.createState();
}
return myWallet.createState().build(context);
},
);
break;
}
},
);
}
}
class MyHome extends StatefulWidget {
#override
MyHomeState createState() => new MyHomeState();
}
class MyHomeState extends State<MyHome> {
#override
void initState() {
super.initState();
print('MyHomeState initState() called');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("test stream"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('HOME 1')
],
),
));
}
}
class MyNearMe extends StatefulWidget {
#override
MyNearMeState createState() => new MyNearMeState();
}
class MyNearMeState extends State<MyNearMe> {
#override
void initState() {
super.initState();
print('MyNearMeState initState() called');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("MyNearMe"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('My Near Me')
],
),
));
}
}
class MyMap extends StatefulWidget {
#override
MyMapState createState() => new MyMapState();
}
class MyMapState extends State<MyMap> {
#override
void initState() {
super.initState();
print('MyMapState initState() called');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("MyMap"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('My Map')
],
),
));
}
}
class MyNotifications extends StatefulWidget {
#override
MyNotificationsState createState() => new MyNotificationsState();
}
class MyNotificationsState extends State<MyNotifications> {
#override
void initState() {
super.initState();
print('MyNotificationsState initState() called');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("MyNotifications"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('My Notifications')
],
),
));
}
}
class MyWallet extends StatefulWidget {
#override
MyWalletState createState() => new MyWalletState();
}
class MyWalletState extends State<MyWallet> {
#override
void initState() {
super.initState();
print('MyWalletState initState() called');
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("MyWallet"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('My Wallet')
],
),
));
}
}
If you want to use another bottom navigation bar instead of cupertino then you can use as below:
I have created a sample example for you where initState() will call every time on tab change whether its same tab or different tab:
First of all import "bmnav: ^0.3.4" library in pubspec.yaml and then copy and paste below code:
import 'package:flutter/material.dart';
import 'package:bmnav/bmnav.dart' as bmnav;
Widget currentScreen = null;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
currentScreen = MyHomeMapSample();
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> {
#override
void initState(){
super.initState();
}
int currentTab = 0;
int prevTab = 0;
final PageStorageBucket bucket = PageStorageBucket();
#override
Widget build(BuildContext ctx) {
debugPrint('currentTab: $currentTab');
return Scaffold(
body: PageStorage(child: currentScreen, bucket: bucket),
bottomNavigationBar: SizedBox(height: 58,
child: bmnav.BottomNav(
index: currentTab,
onTap: (i) {
setState(() {
currentTab = i;
currentScreen = getWidget(context, i);
if(prevTab==currentTab){
if(i==0){
MyHomeMapSample map = currentScreen as MyHomeMapSample;
map.createState().initState();
}else if(i==1){
MyHomeWorkouts map = currentScreen as MyHomeWorkouts;
map.createState().initState();
}
else if(i==2){
MyHomeAccount map = currentScreen as MyHomeAccount;
map.createState().initState();
}
}
prevTab = currentTab;
});
},
labelStyle: bmnav.LabelStyle(visible: true),
items: [
bmnav.BottomNavItem(Icons.map, label: 'Map'),
bmnav.BottomNavItem(Icons.cast, label: 'Workouts'),
bmnav.BottomNavItem(Icons.textsms, label: 'Account'),
],
),
),
resizeToAvoidBottomPadding: true,
);
}
Widget getWidget(BuildContext context, int i){
if(i==0){
return MyHomeMapSample();
}
else if(i==1){
return MyHomeWorkouts();
}else if(i==2){
return MyHomeAccount();
}
}
}
class MyHomeMapSample extends StatefulWidget {
MyHomeMapSample({Key key}) : super(key: key);
#override
MapSample createState() => MapSample();
}
class MapSample extends State<MyHomeMapSample> {
var myVariable = 0;
#override
void initState(){
super.initState();
debugPrint('current: MapSample: initState() called!');
}
#override
Widget build(BuildContext context) {
myVariable = myVariable + 1;
return Scaffold(
appBar: AppBar(
title: Text('MapSample'),
),
body: Center(
child: Text('MapSample details + $myVariable'),
),
resizeToAvoidBottomPadding: true,
);
}
}
class MyHomeWorkouts extends StatefulWidget {
MyHomeWorkouts({Key key}) : super(key: key);
#override
Workouts createState() => Workouts();
}
class Workouts extends State<MyHomeWorkouts> {
var myVariable = 0;
#override
void initState(){
super.initState();
debugPrint('current: Workouts: initState() called!');
}
#override
Widget build(BuildContext context) {
myVariable = myVariable + 1;
return Scaffold(
appBar: AppBar(
title: Text('Workouts'),
),
body: Center(
child: Text('Workouts details + $myVariable'),
),
resizeToAvoidBottomPadding: true,
);
}
}
class MyHomeAccount extends StatefulWidget {
MyHomeAccount({Key key}) : super(key: key);
#override
Account createState() => Account();
}
class Account extends State<MyHomeAccount> {
var myVariable = 0;
#override
void initState(){
super.initState();
debugPrint('current: Account: initState() called!');
}
#override
Widget build(BuildContext context) {
myVariable = myVariable + 1;
return Scaffold(
appBar: AppBar(
title: Text('Account'),
),
body: Center(
child: Text('Account details + $myVariable'),
),
resizeToAvoidBottomPadding: true,
);
}
}