I'm making a cart on flutter. But, I ran into a problem. As planned, the user can add the quantity of goods from the cart. But, due to the fact that I use one variable, the counter increases / decreases everywhere at once. How to fix it? PS: I can't know how much the product will be, it is added by the user himself
Here is my code - Saving State -
int value = 1;
inc() {
setState(() {
value++;
});
}
dec() {
setState(() {
value--;
});
}
Отображение -
Expanded(
child: ListView.builder(
controller: controller,
padding: EdgeInsets.all(5),
itemCount: HomeBody.shoppingBasketHeader!.length,
itemBuilder: (context, index) {
if (index < HomeBody.shoppingBasketHeader!.length) {
return Container(
padding: EdgeInsets.all(5),
margin: EdgeInsets.all(2),
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Container(
width: 150,
child: Image.network('http://10.0.2.2:1337${HomeBody.shoppingBasketImage?[index]}'),
)
],
),
Column(
children: [
Container(
width: 200,
child: Column(
children: [
Container(
margin: EdgeInsets.all(5),
child: Text(' ${HomeBody.shoppingBasketHeader?[index]}', style: TextStyle(fontSize: 15),),
),
],
),
),
Container(
width: 200,
child: Column(
children: [
Container(
margin: EdgeInsets.all(5),
child: Text(' ${HomeBody.shoppingBasketPrice?[index]}', style: TextStyle(fontSize: 15),),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: IconButton(onPressed: () {inc();}, icon: Icon(Icons.add)),
),
Container(
child: Text('$value'),
),
Container(
child: IconButton(onPressed: () {dec();}, icon: Icon(Icons.remove)),
)
],
)
],
),
],
),
);
} else {
return Padding(padding: EdgeInsets.symmetric(
vertical: 10),
child: Center(
child: Text('Список полностью загружен!'),
),
);
}
}
)
**
Option 1
**
Create a separate widget for the below snippet and declare the count variable (value) locally.
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: IconButton(onPressed: () {inc();}, icon: Icon(Icons.add)),
),
Container(
child: Text('$value'),
),
Container(
child: IconButton(onPressed: () {dec();}, icon: Icon(Icons.remove)),
)
],
)
**
Option 2
**
Create a separate class for each row of data and use a List
class CartRow{
int quantity,
double price,
string product,
}
**
Option 3
**
Use option 1 and new class/entity from option 2
-------------------------Option 1 Code -------------------
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class ShoppingCartLine extends StatefulWidget {
const ShoppingCartLine({Key? key}) : super(key: key);
#override
_ShoppingCartLineState createState() => _ShoppingCartLineState();
}
class _ShoppingCartLineState extends State<ShoppingCartLine> {
int? value;
#override
void initState() {
super.initState();
value = 1;
}
#override
Widget build(BuildContext context) {
return _getBody();
}
Widget _getBody(){
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: IconButton(onPressed: () {inc();}, icon: Icon(Icons.add)),
),
Container(
child: Text('${value.toString()}'),
),
Container(
child: IconButton(onPressed: () {dec();}, icon: Icon(Icons.remove)),
)
],
);
}
inc() {
setState(() {
value = (value! + 1);
});
}
dec() {
setState(() {
if(value! > 1){
value = (value! - 1);
}
});
}
}
--------------------------------main.dart--------------------------------
import 'package:flutter/material.dart';
import 'features/shopping_cart_line.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Column(
children: [
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
const ShoppingCartLine(),
const ShoppingCartLine(),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
enter code here
Related
I'm writing an audio player. Like most media players (Youtube, Spotify, etc), I want a "remote" overlay on the screen while media is playing. No matter what the user is doing, they should be able to control the media.
I accomplished that with a Stack under MaterialApp
MaterialApp(
title: 'MyApp',
navigatorObservers: [gRouteObserver],
routes: appRoutes,
builder: (context, child) {
return Stack(children: [
child!,
Positioned(
bottom: 55,
width: MediaQuery.of(context).size.width,
child: StatefulBuilder(builder: (context, _setState) {
gPlayer.widgetSBRefresher = _setState;
return gPlayer.started ? gPlayer.widget : const SizedBox(height: 0);
}))
]);
});
gPlayer.widget references this
class MiniPlayer extends StatefulWidget {
const MiniPlayer({Key? key}) : super(key: key);
#override
State<MiniPlayer> createState() => MiniPlayerState();
}
class MiniPlayerState extends State<MiniPlayer> with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(context) {
super.build(context);
return Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.black,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Column(
children: [
Material(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AvatarAlone(id: gPlayer.current!.owner),
Expanded(
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text(gPlayer.playing
? "Now Playing"
: "Paused"),
),
),
// here is the code I'll
// be talking about -->
IconButton(
color: Colors.white,
iconSize: 20,
icon: const Icon(MyIcons.bookmark),
onPressed: gPlayer.bookmarkBuilder,
),
InkWell(child: Icon(gPlayer.playing ? MyIcons.pauseCircle : MyIcons.playCircle, size: 50), onTap: gPlayer.playPause)
],
),
),
],
),
),
),
));
}
refresh() {
setState(() {});
}
}
I used a code comment to point out this icon button.
IconButton(
color: Colors.white,
iconSize: 20,
icon: const Icon(MyIcons.bookmark),
onPressed: gPlayer.bookmarkBuilder,
),
So, when this widget is open and the app is on the home route ("/"), I can do
bookmarkBuilder() {
Scaffold.of(gScaffApp.currentContext!).openDrawer();
}
and it will open the drawer.
I've attached the same drawers to all my routes' scaffolds.
When other routes are up, with their own scaffolds, I want bookmarkBuilder to open the drawer on the topmost route. But I can't quite figure out how.
So I have a working solution to this, but I don't love it.
I created a global variable, gScaffs, with gScaffApp as the first element.
List<GlobalKey<ScaffoldState>> gScaffs = [gScaffApp];
My secondary routes all use the same base scaffold widget
class _CardScaffoldState extends State<CardScaffold> {
#override
initState() {
super.initState();
gScaffs.add(GlobalKey());
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(key: gScaffs.last,
drawer: DrawerBookmarks()
...
And the dispose method looks like this.
#override
dispose() {
super.dispose();
gScaffs.removeLast();
}
And then, in my bookmarkBuilder function, I have this.
It's not clear to me why, but gScaffApp needs the drawer triggered one way, while the CardScaffolds need the drawer triggered the other way.
bookmarkBuilder() {
if (gScaffApp == gScaffs.last) {
Scaffold.of(gScaffApp.currentContext!).openDrawer();
} else {
gScaffs.last.currentState!.openDrawer();
}
}
When I click text fields on the main page (main.dart) which is the default dart given by the flutter. I can see a glitch when soft keyboard appears and there is no delay when soft keyboard disappears.I have attached a gif below for this case.
void main() {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: primaryColor, //blue
statusBarIconBrightness: Brightness.dark,
));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.pink,
primaryColor: primaryColor,
primaryColorBrightness: Brightness.dark,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
// setState(() {
// // This call to setState tells the Flutter framework that something has
// // changed in this State, which causes it to rerun the build method below
// // so that the display can reflect the updated values. If we changed
// // _counter without calling setState(), then the build method would not be
// // called again, and so nothing would appear to happen.
// _counter++;
// });
setState(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PhoneAuth()));
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text('hell0000000'),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Container(
color: Colors.white,
child: ListView(
children: [
Column(
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
SizedBox(
height: 200,
),
Align(
alignment: Alignment.bottomCenter,
child: new Container(
child: TextField(
decoration: new InputDecoration(
hintText: 'Chat message',
),
),
),
),
],
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
main.dart glich
Also, When I click text fields on the other page (UserChatView.dart). I can see a glitch when soft keyboard appearing and disappearing. In this dart file, That glitch happening for both actions(Keyboard opening and closing). I have attached a gif below for this case.
class UserChatView extends StatelessWidget{
#override
Widget build(BuildContext context) {
return UserChatViewPage();
}
}
class UserChatViewPage extends StatefulWidget {
UserChatViewPage({Key key}) : super(key: key);
#override
_UserChatViewPageState createState() => _UserChatViewPageState();
}
class _UserChatViewPageState extends State<UserChatViewPage> {
final TextEditingController _textController = new TextEditingController();
#override
Widget build(BuildContext context) {
final focus = FocusNode();
return new Scaffold(
backgroundColor: Colors.red, // Scaffold background Color
appBar: new AppBar(
title: Row(
children: <Widget>[
// new Container(
// child: CircleAvatar(
// backgroundImage: AssetImage("assets/male_icon.png"),
// )
// ),
new SizedBox(
width: 5.00,
),
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget> [
new Container(
child: new Text("Alex Marko",
style: TextStyle(color: Colors.white,
fontFamily: 'Roboto_Bold',
letterSpacing: 1.00
),
),
),
new Container(
child: new Text("Online",
style: TextStyle(color: Colors.white,
fontFamily: 'Roboto_Medium',
letterSpacing: 1.00,
fontSize: 12.00,
),
),
),
],
),
],
),
centerTitle: false,
titleSpacing: 0.0,
backgroundColor: primaryColor,
elevation: 0.0,
bottomOpacity: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.expand_more_rounded,
color: Colors.white,
),
onPressed: () {
// do something
},
),
],
),
body: Center(
child: new Container(
color: Colors.grey,
child: new Column(
children: <Widget>[
new Expanded(
child: _PageListView(),
),
new Container(
color: Colors.yellow,
padding: new EdgeInsets.all(10.0),
child: _buildTextComposer(),
),
],
),
),
),
);
}
Widget _buildTextComposer() {
return new Container(
color: Colors.yellow,//modified
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: new Row(
children: <Widget>[
new Flexible(
child: new TextField(
controller: _textController,
onSubmitted: _handleSubmitted,
decoration: new InputDecoration.collapsed(
hintText: "Send a message"),
),
),
new Container(
margin: new EdgeInsets.symmetric(horizontal: 4.0),
child: new IconButton(
icon: new Icon(Icons.send),
onPressed: () => _handleSubmitted(_textController.text)),
),
],
),
);
}
Widget _PageListView(){
return new Container(
child: ListView.builder(
reverse: true,
itemCount: 20,
itemBuilder: (context, position) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(position.toString(), style: TextStyle(fontSize: 22.0),),
),
);
},
),
);
}
UserChatView.dart Glich
The reason of this so called Glitch is that the default behaviour of the flutter scaffold widget is to resize it's body when soft keyboard opens up or closes down.
While the flutter scaffold is notified of any of the above two events, it will start resizing the widgets under its body to match the new state. The speed of resizing may differ based on the comlplexity of build process of the widget on screen & processing speed of the device itself.
What you can do is add a flag called resizeToAvoidBottomInset in the scaffold widget in your app, like this:
Scaffold(
...
resizeToAvoidBottomInset: false,
)
What this does is, It notifies the scaffole to not resize the widget under its body on keyboard up or down states.
So, unless you want to explicitely resize the content of the screen on keyboard state, this is a solution to your glitch.
On the other hand, if you want to resize the content, you can choose to modularize/breakdown the widgets that you have on screen to smallest possible combination & make the layout simpler so that the glitch portion of the resizing is taken care of by the speed of rebuild process.
Your keyboard is producing that effect because of the ListView.builder. Add extra properties to your ListView like this
Widget _PageListView(){
return new Container(
child: ListView.builder(
addAutomaticKeepAlives: true, // Add this property
cacheExtent: double.infinity, // And this one
reverse: true,
itemCount: 20,
itemBuilder: (context, position) {
return Card( /* It's better to have here a separated StatefulWidget with AutomaticKeepAliveClientMixin */
// ...
);
},
),
);
}
I'm developing a Flutter app, and I am trying to create a reusable button widget to be used in various places throughout my app. I want every button to be required to have text, and an onpressed function, with an option of having an image. Whenever I try to create a button that doesn't have the buttonImage property, I get a "Row's Children must not contain any null values" error, and I'm having issues trying to solve it. Below is code for my ReusableButton Widget and the implementation. Any help is appreciated
import 'package:flutter/material.dart';
class ReusableButton extends StatelessWidget {
ReusableButton({
this.buttonImage,
#required this.buttonText,
#required this.onPressed,
this.buttonColor,
});
final String buttonText;
final Function onPressed;
final Color buttonColor;
final Image buttonImage;
#override
Widget build(BuildContext context) {
return OutlineButton(
onPressed: onPressed,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: buttonColor),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
buttonImage,
Text(
buttonText,
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
],
),
),
);
}
}
Here is the code in which I am implementing the ReusableButton widget
class LoginPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Container(
child: Center(
child: Column(
children: <Widget>[
ReusableButton(
buttonImage: Image.asset('images/google_logo.png', height: 25.0),
buttonText: 'UserName',
buttonColor: kButtonBorderColor,
onPressed: ()
{
},
),
ReusableButton(
buttonText: 'Password',
buttonColor: kButtonBorderColor,
onPressed: ()
{
},
),
],
),
),
),
),
],
)
);
}
}
You need to return Container() if buttonImage is null
Row widget do not know how to render null
you must tell Row widget to render empty content if it's null
Please see full code and demo below
children: <Widget>[
buttonImage == null ? Container() : buttonImage,
code snippet
class ReusableButton extends StatelessWidget {
ReusableButton({
this.buttonImage,
#required this.buttonText,
#required this.onPressed,
this.buttonColor,
});
final String buttonText;
final Function onPressed;
final Color buttonColor;
final Image buttonImage;
#override
Widget build(BuildContext context) {
return OutlineButton(
onPressed: onPressed,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: buttonColor),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
buttonImage == null ? Container() : buttonImage,
Text(
buttonText,
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
],
),
),
);
}
}
demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class ReusableButton extends StatelessWidget {
ReusableButton({
this.buttonImage,
#required this.buttonText,
#required this.onPressed,
this.buttonColor,
});
final String buttonText;
final Function onPressed;
final Color buttonColor;
final Image buttonImage;
#override
Widget build(BuildContext context) {
return OutlineButton(
onPressed: onPressed,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: buttonColor),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
buttonImage == null ? Container() : buttonImage,
Text(
buttonText,
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
],
),
),
);
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ReusableButton(
buttonImage: Image.asset('assets/images/alarm.png', height: 25.0),
buttonText: 'UserName',
buttonColor: Colors.blue,
onPressed: ()
{
},
),
ReusableButton(
buttonText: 'Password',
buttonColor: Colors.blue,
onPressed: ()
{
},
),
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),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
You're not passing an image to the second button that very much Equal to 'passing a null value'
In constructor check whether the image is null, if it is null set an empty container which should solve the problem
if(this.image==null) this.image = Container(width:0,height:0);
or in short
this.image?? = Container(width:0,height:0);
Or else in build check for whether the image is not null if it is not null then only place it in the row
Or you can use shorthand buttonImage ?? Container() it is equally buttonImage == null ? Container() : buttonImage,
If you ever need to add multiple child items to a Column based on a single "if":
Example:
Column(
children: [
Container(),
if (<some conditional statement>) ...[
Container(),
Container(),
Container(),
Container()
],
] // children
), // Column
I am new to flutter. I want to make a widget which is marked in red in the picture.
I tried using Transform but the widgets (Text widgets for 'Overview', 'Portfolio', etc.) are overlapping on each other.
How can I build it?
You can use RotatedBox with quarterTurns 3
RotatedBox(quarterTurns: 3, child: Text('Overview'))
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: RotatedBox(quarterTurns: 3, child: Text('Overview')),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RotatedBox(quarterTurns: 3, child: Text('Profile')),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RotatedBox(quarterTurns: 3, child: Text('Bio')),
),
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),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Yes. Flutter has NavigationRail. You can see sample and documentation from their official docs.
Flutter added this support as it becomes standard in Material design 3 here.
Just keep attention to their usage recommendations.
The navigation rail is meant for layouts with wide viewports, such as a desktop web or tablet landscape layout. For smaller layouts, like mobile portrait, a BottomNavigationBar should be used instead.
And below is sample flutter code for your convenience.
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(
theme: ThemeData(
colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
home: const NavRailExample(),
);
}
}
class NavRailExample extends StatefulWidget {
const NavRailExample({super.key});
#override
State<NavRailExample> createState() => _NavRailExampleState();
}
class _NavRailExampleState extends State<NavRailExample> {
int _selectedIndex = 0;
NavigationRailLabelType labelType = NavigationRailLabelType.all;
bool showLeading = false;
bool showTrailing = false;
double groupAligment = -1.0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
groupAlignment: groupAligment,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: labelType,
leading: showLeading
? FloatingActionButton(
elevation: 0,
onPressed: () {
// Add your onPressed code here!
},
child: const Icon(Icons.add),
)
: const SizedBox(),
trailing: showTrailing
? IconButton(
onPressed: () {
// Add your onPressed code here!
},
icon: const Icon(Icons.more_horiz_rounded),
)
: const SizedBox(),
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('selectedIndex: $_selectedIndex'),
const SizedBox(height: 20),
Text('Label type: ${labelType.name}'),
const SizedBox(height: 10),
OverflowBar(
spacing: 10.0,
children: <Widget>[
ElevatedButton(
onPressed: () {
setState(() {
labelType = NavigationRailLabelType.none;
});
},
child: const Text('None'),
),
ElevatedButton(
onPressed: () {
setState(() {
labelType = NavigationRailLabelType.selected;
});
},
child: const Text('Selected'),
),
ElevatedButton(
onPressed: () {
setState(() {
labelType = NavigationRailLabelType.all;
});
},
child: const Text('All'),
),
],
),
const SizedBox(height: 20),
Text('Group alignment: $groupAligment'),
const SizedBox(height: 10),
OverflowBar(
spacing: 10.0,
children: <Widget>[
ElevatedButton(
onPressed: () {
setState(() {
groupAligment = -1.0;
});
},
child: const Text('Top'),
),
ElevatedButton(
onPressed: () {
setState(() {
groupAligment = 0.0;
});
},
child: const Text('Center'),
),
ElevatedButton(
onPressed: () {
setState(() {
groupAligment = 1.0;
});
},
child: const Text('Bottom'),
),
],
),
const SizedBox(height: 20),
OverflowBar(
spacing: 10.0,
children: <Widget>[
ElevatedButton(
onPressed: () {
setState(() {
showLeading = !showLeading;
});
},
child:
Text(showLeading ? 'Hide Leading' : 'Show Leading'),
),
ElevatedButton(
onPressed: () {
setState(() {
showTrailing = !showTrailing;
});
},
child: Text(
showTrailing ? 'Hide Trailing' : 'Show Trailing'),
),
],
),
],
),
),
],
),
),
);
}
}
Hi guys im flutter and dart new-be
i make photoupload function
But I got into trouble while I was making it.
class pictureBox() can't recognize getImage() ,,
Its my whole code :
class writeprofile extends StatefulWidget {
#override
_writeprofileState createState() => _writeprofileState();
}
class _writeprofileState extends State<writeprofile> {
File _image;
#override
Widget build(BuildContext context) {
Future getImage() async{
var image= await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
print('Image Path $_image');
});
}
Future uploadPic(BuildContext context) async{
String filName = basename(_image.path);
StorageReference firebaseStorageRef = FirebaseStorage.instance.ref().child(filName);
StorageUploadTask uploadTask = firebaseStorageRef.putFile(_image);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
setState(() {
print("Profile pic upload !!");
Scaffold.of(context).showSnackBar(SnackBar(content: Text('Profile pic Upload !!')));
});
}
return Scaffold(
body: Builder(
builder: (context)=> Center(
child: Container(
child: Container(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 70),
child: Text(
'사진 선택',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w500,
),
),
),
Padding(
padding: EdgeInsets.only(top: 10, bottom: 50),
child: Container(
height: 1,
width: MediaQuery.of(context).size.width / 1.4,
color: Colors.black26,
),
),
Container(
width: MediaQuery.of(context).size.width / 1.5,
height: MediaQuery.of(context).size.height / 15,
alignment: FractionalOffset.center,
decoration: BoxDecoration(
color: const Color.fromRGBO(250, 80, 120, 1),
borderRadius: BorderRadius.all(const Radius.circular(30)),
),
child: Text(
"가이드 라인을 읽어주세요 !",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w300,
letterSpacing: 0.3,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 100),
child: Row(
children: <Widget>[
PictureBox(),
PictureBox(),
PictureBox(),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
children: <Widget>[
PictureBox(),
PictureBox(),
PictureBox(),
],
),
),
InkWell(
onTap: (){uploadPic(context);},
child: Padding(
padding: EdgeInsets.only(top: 50),
child: Container(
width: MediaQuery.of(context).size.width / 3,
height: MediaQuery.of(context).size.height /20,
alignment: FractionalOffset.center,
decoration: BoxDecoration(
color: const Color.fromRGBO(250, 80, 100, 1),
borderRadius: BorderRadius.all(const Radius.circular(30)),
),
child: Text(
"Next",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w500,
letterSpacing: 0.3,
),
),
),
),
),
],
),
),
),
),
),
);
}
}
class PictureBox extends StatefulWidget {
#override
_PictureBoxState createState() => _PictureBoxState();
}
class _PictureBoxState extends State<PictureBox>{
#override
Widget build(BuildContext context) {
return Container(
child: InkWell(
onTap: (){getImage(context);},
child: Padding(
padding: EdgeInsets.only(left: 10),
child:Container(
width: MediaQuery.of(context).size.width / 3.3,
height: MediaQuery.of(context).size.height / 7,
color: Colors.black12,
child: Center(
child: (_image!=null)? Image.file(_image, fit:BoxFit.fill)
:Icon(
Icons.camera_alt,
color: Colors.black26,
),
),
),
),
),
);
}
}
This is my code , i want use to 'Future getImage()' in PictureBox
How to running getImage() in PictureBox?
Additionally how to solve error 'undefined name '_image'' in PictureBox ?
_ means private variable. So remove _ and try.
If you want to call a function inside a StatefulWidget widget
You need to use GlobalKey to keep YourFormState and call function inside YourFormState with key.currentState
The following demo is appbar action call a function inside a form StatefulWidget, so appbar action and form submit button can use same function and snackbar also work fine
code snippet
final key = new GlobalKey<MyCustomFormState>();
...
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
// action button
IconButton(
icon: Icon(Icons.access_alarm),
onPressed: () {
key.currentState.validateform();
},
),
]),
...
children: <Widget>[
MyCustomForm(key: key),
...
class MyCustomForm extends StatefulWidget {
MyCustomForm({ Key key }) : super(key: key);
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
final key = new GlobalKey<MyCustomFormState>();
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
var myCustomForm = MyCustomForm();
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
actions: <Widget>[
// action button
IconButton(
icon: Icon(Icons.access_alarm),
onPressed: () {
key.currentState.validateform();
},
),
]),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MyCustomForm(key: key),
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),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class MyCustomForm extends StatefulWidget {
MyCustomForm({ Key key }) : super(key: key);
#override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a GlobalKey<FormState>,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
onPressed: () {
// Validate returns true if the form is valid, or false
// otherwise.
validateform();
},
child: Text('Submit'),
),
),
],
),
);
}
void validateform() {
// Validate returns true if the form is valid, or false
// otherwise.
if (_formKey.currentState.validate()) {
// If the form is valid, display a Snackbar.
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('Processing Data')));
}
}
}
#Killer Whale, if you want to call child method from parent and setState() in child, then you can use GlobalKey.
GlobalKey<WriteprofileState> globalKey =new GlobalKey<WriteprofileState>();
_writeprofileState remote private identifier and write as WriteprofileState.
then pass global key from parent to WriteprofileState
like :
Widget build(BuildContext conext){
return Container(
child: Writeprofile(
key:globalKey
)
);
}
and then pass this key to super class, Writeprofile(Key key):super(key:key);
and now from parent class you can access all method of child.
globalKey.currentState.methodName();