I am working in an cart kind of application, where I need to show cart item counts. How to show item counts in Toolbar actions. I surfed lot couldn't find the solution.
You can simply add a button with image and text as Action to AppBar widget. Then whenever you adding the item, you need to update the text inside the Action. Here a working simple example:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: "Sample",
home: new Home(),
));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
// save the total of the item here.
int _total = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
// add the AppBar to the page
appBar: new AppBar(
actions: <Widget>[
// Add a FlatButton as an Action for the AppBar
FlatButton(
onPressed: () => {},
child: Row(
children: <Widget>[
Icon(Icons.shop),
Text("Total $_total")
],
),
)
],
),
floatingActionButton: new FloatingActionButton(
child: Icon(Icons.add),
onPressed: _increaseTotal,
tooltip: "Add",
),
);
}
// increase the total item whenever you click the FloatingActionBar
void _increaseTotal() {
setState(() {
_total++;
});
}
}
Related
Flutter beginner needs help.
Is it possible that the app by himself without a press of a button, navigates from a second screen to the home screen after a period of time, if there is no any interaction on the second Screen.
For example in the following code is it possible to make this?
I don't know how to implement this.
Thanks in advance for some help
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Navigate to a new screen on Button click'),
backgroundColor: Colors.teal),
body: Center(
child: FlatButton(
color: Colors.teal,
textColor: Colors.white,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>Screen2()));
},
child: Text('GO TO SCREEN 2'),
),
),
);
}
}
class Screen2 extends StatefulWidget {
#override
_Screen2State createState() => _Screen2State();
}
class _Screen2State extends State<Screen2> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Navigate to a new screen on Button click'),
backgroundColor: Colors.blueAccent),
body: Center(
child: FlatButton(
color: Colors.blueAccent,
textColor: Colors.white,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>Home()));
},
child: Text('GO TO HOME'),
),
),
);
}
}
First, I would recommend pop and not push because Flutter navigator works like a stack.
Next, you can set a timer in the initState function:
#override
void initState() {
Timer(Duration(seconds: 3), () {
Navigator.of(context).pop(MaterialPageRoute(builder: (context) => Home()));
});
super.initState();
}
for a better solution, I would set a timer in the initState function and wrap the entire page with GestureDetector, so that each gesture resets the timer.
Use GestureDetector's behavior property and pass HitTestBehavior.opaque to it, which recognizes entire screen and detects the tap when you tap anywhere on the screen. like this:
import 'dart:async';
import 'package:flutter/material.dart';
class Screen2 extends StatefulWidget {
#override
_Screen2State createState() => _Screen2State();
}
class _Screen2State extends State<Screen2> {
Timer? searchOnStoppedTyping;
_onChangeHandler() {
const duration = Duration(milliseconds: 800); // set the duration that you want call pop() after that.
if (searchOnStoppedTyping != null) {
searchOnStoppedTyping?.cancel(); // clear timer
}
searchOnStoppedTyping = new Timer(duration, () => navigateHome());
}
navigateHome() {
Navigator.of(context).pop(MaterialPageRoute(builder: (context) => Home()));
}
#override
void initState() {
_onChangeHandler();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Navigate to a new screen on Button click'), backgroundColor: Colors.blueAccent),
body: GestureDetector(
//Use GestureDetector's behavior property and pass HitTestBehavior.opaque to it, which recognizes entire screen and detects the tap when you tap anywhere on the screen.
behavior: HitTestBehavior.opaque,
onTap: _onChangeHandler,
child: yourBody...,
),
);
}
}
class Screen2 extends StatefulWidget {
#override
_Screen2State createState() => _Screen2State();
}
class _Screen2State extends State<Screen2> {
// try to add init state and add timer inside it then it will navigate after duration
void initState() {
super.initState();
Timer(Duration(seconds: 4), (){
Navigator.of(context).pop(MaterialPageRoute(builder: (context)=>Home()));
});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Navigate to a new screen on Button click'),
backgroundColor: Colors.blueAccent),
body: Center(
child: FlatButton(
color: Colors.blueAccent,
textColor: Colors.white,
onPressed: () {
// i moved this line inside the Timer , look at initState
},
child: Text('GO TO HOME'),
),
),
);
}
}
I have faced the flutter tooltip problem
Here is my code:
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
#override
_State createState() => _State();
}
class _State extends State<MyApp> {
String _value = 'Hello again';
void _onClicked() => setState(() => _value = new DateTime.now().toString());
#override
Widget build(BuildContext context) {
return Scaffold(
// key: _scaffoldstate,
appBar: AppBar(
title: Text('Name here'),
),
body: Container(
padding: EdgeInsets.all(32.0),
child: Center(
child: Column(
children: <Widget>[
Text(_value),
IconButton(
icon: Icon(Icons.timer),
onPressed: _onClicked,
tooltip: "Hi I'm tooltip", // way one
),
Tooltip(
// way two
message: 'I am a Tooltip',
child: Text('Hover over the text to show a tooltip.'),
)
],
),
),
),
);
}
}
I have tried two way but doesn't work in any way, I don't know where is a problem.
Is it a problem with my column widget?
flutter version: 2.0.3
any suggestion, please.
ToolTips gets visible when you hover on those Widgets. In a mobile phone, it's not possible to hover on widgets without a mouse so try long pressing on those widgets to view tooltips.
ToolTips are visible when hovering on those widgets on the web. Check this DartPad
New to this so I have no clue whats wrong here. I need the code to add 1 to _count when the button is pressed but nothing happens when the button is pressed
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
int _count = 0;
void main() {
var app = MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_count++;
return _count.toString();
},
),
appBar: AppBar(title: Text('Welcome')),
body: Center(
child: Text('You have pressed the button $_count times.'),
),
),
);
runApp(app);
}
To update state you need StatefulWiget to have a state with your count data, then call setState when you change your data:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _count = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState((){_count++;});
},
),
appBar: AppBar(title: Text('Welcome')),
body: Center(
child: Text('You have pressed the button $_count times.'),
),
),
);
}
}
You can fast check result copying this code to dartpad and pressing run.
It will be good start for you if you check this page, knowing what is state in flutter.
I am new to flutter and Im trying to rebuild the demo app. How can I add the FloatingActioButton to the App it seems that I can't add another body or something. How can I do this ?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
int _counter = 0;
void increase_Counter() {
setState(() {
_counter += 1;
});
}
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(
appBar: AppBar(
title: Text("Demo App"),
),
body: Center(
child: Text("Your press button $_counter times"),)
body:(FloatingActionButton(onPressed: increase_Counter,)
),)
,
);
}
}
You can check the below code. Floating action button always goes inside scaffold.
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(
appBar: AppBar(
title: Text("Demo App"),
),
body: Center(
child: Text("Your press button $_counter times"),),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
),
);
}
And you can also follow FloatingActionButton to get better understanding.
I'm building an app with 3 items in the bottom navigation bar. When I change the tab, a different widget is rendering. So far, so good...
import 'package:flutter/material.dart';
class BottomTest extends StatefulWidget {
State createState() => new _BottomTestState();
}
class _BottomTestState extends State<BottomTest> {
List<Widget> _pages;
Widget _selectedContent;
int _bottomIndex;
#override
void initState() {
_bottomIndex = 0;
super.initState();
}
#override
Widget build(BuildContext context) {
_definePages();
return Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Test'),
),
body: _selectedContent ?? _pages[_bottomIndex],
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.add),
title: Text("Red")
),
BottomNavigationBarItem(
icon: Icon(Icons.location_on),
title: Text("Blue")
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
title: Text("Green")
)
],
currentIndex: _bottomIndex,
onTap: _onTabTapped,
)
);
}
_definePages() {
_pages = [
Container(
color: Colors.red,
child: Stack(children: <Widget>[
_defineFloatingActionButton(),
])
),
Container(color: Colors.blue),
Container(color: Colors.green),
];
}
_defineFloatingActionButton() {
return Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
//TODO: How to navigate to another page with still displaying the bottom navigation bar?
}
),
);
}
void _onTabTapped(int index) {
setState(() {
_bottomIndex = index;
_selectedContent = _pages[index];
});
}
}
//POST
class Post extends StatefulWidget {
State createState() => new _PostState();
}
class _PostState extends State<Post> {
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
PostHeader(),
Text('This is a post.')
]);
}
}
//POSTHEADER
class PostHeader extends StatefulWidget {
State createState() => new _PostHeaderState();
}
class _PostHeaderState extends State<PostHeader> {
#override
Widget build(BuildContext context) {
return ListTile(
leading: Text('Author'),
onTap: () {
//TODO: This should navigate to another page but still displaying the bottom navigation bar, too.
},
);
}
}
But I can't figure out a best practice for more advance navigation. There are 2 problems that I'm currently facing.
When tabbing the FloatingActionButton on the first page, I want to display a fourth page but the BottomNavigationBar still needs to be visible and operable.
Building a more complex app, I'm dealing with a handful of nested classes. So on my root page, there is a class "Post" and the post contains a class "PostHeader". In PostHeader, there is a ListTile with an onTap callback that should affect my _selectedContent. How do I define this callback? Passing it trough all the different classes didn't seem right.
I thought about defining it in my BottomTest.dart and passing it trough Post and PostTile but that doesn't seem like best practice to me, especially when talking about lots of required callbacks.
Thank you very, very much in advance!
I'm assuming that the fourth page will be shown as any of the other three pages and since the button is in the first page, the fourth page will take the place of the first page and still signal the first bottom "red" field as active.
If that is the case you should create an independent widget for the first page that includes all the logic you need to show other content. Thus you avoid rebuilding the main layout, including the BottomNavigationBar.
You could use something along these lines, by using a FirstPage widget:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new BottomTest(),
);
}
}
class BottomTest extends StatefulWidget {
State createState() => new _BottomTestState();
}
class _BottomTestState extends State<BottomTest> {
List<Widget> _pages;
Widget _selectedContent;
int _bottomIndex;
#override
void initState() {
_bottomIndex = 0;
super.initState();
}
#override
Widget build(BuildContext context) {
_definePages();
return Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Test'),
),
body: _selectedContent ?? _pages[_bottomIndex],
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.add), title: Text("Red")),
BottomNavigationBarItem(
icon: Icon(Icons.location_on), title: Text("Blue")),
BottomNavigationBarItem(
icon: Icon(Icons.people), title: Text("Green"))
],
currentIndex: _bottomIndex,
onTap: _onTabTapped,
));
}
_definePages() {
_pages = [
FirstPage(),
Container(color: Colors.blue),
Container(color: Colors.green),
];
}
void _onTabTapped(int index) {
setState(() {
_bottomIndex = index;
_selectedContent = _pages[index];
});
}
}
//POST
class Post extends StatefulWidget {
State createState() => new _PostState();
}
class _PostState extends State<Post> {
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[PostHeader(), Text('This is a post.')]);
}
}
//POSTHEADER
class PostHeader extends StatefulWidget {
State createState() => new _PostHeaderState();
}
class _PostHeaderState extends State<PostHeader> {
#override
Widget build(BuildContext context) {
return ListTile(
leading: Text('Author'),
onTap: () {
//TODO: This should navigate to another page but still displaying the bottom navigation bar, too.
},
);
}
}
class FirstPage extends StatefulWidget {
#override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
bool showFirst = true;
_defineFloatingActionButton() {
return Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _onButtonPressed,
),
);
}
_onButtonPressed() {
setState(() {
showFirst = !showFirst;
});
}
_buildFirst() {
return Container(
color: Colors.red,
child: Stack(children: <Widget>[
_defineFloatingActionButton(),
]));
}
_buildFourth() {
return Container(
color: Colors.grey,
child: Stack(children: <Widget>[
_defineFloatingActionButton(),
]));
}
#override
Widget build(BuildContext context) {
return showFirst ? _buildFirst() : _buildFourth();
}
}
For the second point, perhaps you should open another question so you keep two, more or less, unrelated matters in different answers.