Flutter Widget: set width to leftover width without using absolute number - flutter

I have the following Flutter Widget. On the right side to "+", we still see a lot of free gray space. How can I set the width of the white box to use all the leftover space, without using the absolute number?
import 'package:flutter/material.dart';
class QtyWidget extends StatefulWidget {
String title;
QtyWidget({this.title});
#override
_QtyWidgetState createState() => new _QtyWidgetState();
}
class _QtyWidgetState extends State<QtyWidget> {
int _itemCount = 1;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
color: Colors.grey[200],
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 100,
padding: EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Text(
'Qty',
style: TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
color: Colors.grey[600]),
),
),
Container(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.amber[800],
),
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: Row(
children: <Widget>[
IconButton(icon: new Icon(Icons.remove),
onPressed: () {
setState(() {
_itemCount = _itemCount - 1 ;
if (_itemCount < 0) {
_itemCount = 1;
}
});
}),
Text(_itemCount.toString()),
IconButton(icon: new Icon(Icons.add),
onPressed: ()=>setState(()=>_itemCount++))
],
),
),
]),
);
}
}

You can copy paste run full code below
You can use wrap Container with Expanded and Row use MainAxisAlignment.center and CrossAxisAlignment.center
code snippet
Expanded(
child: Container(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.amber[800],
),
borderRadius: BorderRadius.all(Radius.circular(10))),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class QtyWidget extends StatefulWidget {
String title;
QtyWidget({this.title});
#override
_QtyWidgetState createState() => new _QtyWidgetState();
}
class _QtyWidgetState extends State<QtyWidget> {
int _itemCount = 1;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
color: Colors.grey[200],
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 100,
padding: EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Text(
'Qty',
style: TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
color: Colors.grey[600]),
),
),
Expanded(
child: Container(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.amber[800],
),
borderRadius: BorderRadius.all(Radius.circular(10))),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
IconButton(
icon: new Icon(Icons.remove),
onPressed: () {
setState(() {
_itemCount = _itemCount - 1;
if (_itemCount < 0) {
_itemCount = 1;
}
});
}),
Text(_itemCount.toString()),
IconButton(
icon: new Icon(Icons.add),
onPressed: () => setState(() => _itemCount++))
],
),
),
),
]),
);
}
}
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: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
QtyWidget(),
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

How to wrap the Row according to child Text widget in Flutter

I have this piece of code inside a scaffold with SafeArea:
Column(
children: [Flexible(
fit: FlexFit.loose,
child: Container(
// width: 130,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [Icon(Icons.ac_unit), Text("Trending")],
),
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[300]),
),
)]
)
Which gives the following result:
What I want to achieve is this:
How do I make the row warp around the text.
from the documentation
Wrap(
spacing: 8.0, // gap between adjacent chips
runSpacing: 4.0, // gap between lines
children: <Widget>[
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('AH')),
label: Text('Hamilton'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('ML')),
label: Text('Lafayette'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('HM')),
label: Text('Mulligan'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('JL')),
label: Text('Laurens'),
),
],
)
if you want to use that row just do
Row(
mainAxisSize: MainAxisSize.min
children: [
...
])
replace that Chip() with the above row
Edit:
replace the Chip() with that _buildChip() custom widget something like this, It should give you a better control over the widget
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(
home: MyPage(),
));
}
class MyPage extends StatelessWidget {
Widget _buildChip() {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.grey.withOpacity(.4) ),
child: InkWell(
highlightColor: Colors.blue.withOpacity(.4),
splashColor: Colors.green,
borderRadius: BorderRadius.circular(20),
onTap: () {
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 7),
child: Row(
mainAxisSize: MainAxisSize.min,
children:[
Icon(Icons.ac_unit, size: 14),
SizedBox(width: 10),
Text("Trending")
]),
),
),
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Wrap(
spacing: 8.0, // gap between adjacent chips
runSpacing: 4.0, // gap between lines
children: <Widget>[
_buildChip(),
_buildChip(),
_buildChip(),
_buildChip(),
_buildChip(),
],
)
);
}
}
let me know if It is what you want, so that I edit that answer
Take a look at this example. You should be using Wrap and RichText to achieve this design. Not Flexible, because it will take all the available space.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key? key, required this.title}) : super(key: key);
#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: Wrap(children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.grey[300]),
child: RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Icon(Icons.ac_unit, size: 14),
),
TextSpan(
text: "Trending",
),
],
),
),
),
SizedBox(width: 5,),
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.grey[300]),
child: RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Icon(Icons.ac_unit, size: 14),
),
TextSpan(
text: "Trending",
),
],
),
),
)
]),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Show widget when button is clicked (Dart, Flutter)

how can I show a widget (for example some more buttons) when a button is clicked.
FlatButton(
onPressed: () {
//render the new widgets
},
child: Icon(
Icons.close,
color: Colors.white,
),
));
This is the parent class
class StopStream extends StatelessWidget
You can conditionally show / hide a widget(s) with a help of a variable.
You need a StatefulWidget to change the state of a widget i.e to dynamically show / hide (widgets).
Please see the following code, I use a bool showWidget to show or hide more FlatButton's in a Row :
import 'package:flutter/material.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
bool showWidget = false;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
showWidget
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(
onPressed: () {},
child: const Icon(Icons.ac_unit),
),
FlatButton(
onPressed: () {},
child: const Icon(Icons.accessible),
),
FlatButton(
onPressed: () {},
child: const Icon(Icons.backpack),
),
FlatButton(
onPressed: () {},
child: const Icon(Icons.cached),
),
],
)
: Container(),
FlatButton(
onPressed: () {
setState(() {
showWidget = !showWidget;
});
},
child: const Icon(
Icons.close,
color: Colors.white,
),
),
],
);
}
}
Have a state variable (either in State or in something like Provider or Riverpod) that will be toggled by your onPressed: callback. Then allow that variable to control whether or not the widget in question is shown or omitted from the widget tree.
You can use a bool variable Forexample in my case isSwitched and set its value to false. When the user clicks on the button, set its value to true and use conditional operator to show more widgets as follows:
class CoverScreen extends StatefulWidget {
#override
_CoverScreenState createState() => _CoverScreenState();
}
class _CoverScreenState extends State<CoverScreen> {
bool isSwitched = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 70,
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
child: Text('WELCOME'),
),
],
)),
body: Padding(
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(children: <Widget>[
Container(
padding: const EdgeInsets.all(15),
child: Text(
'COVER LETTER:',
style: TextStyle(
color: Colors.teal,
fontSize: 25,
fontWeight: FontWeight.w500),
)),
Container(
child: Switch(
value: isSwitched,
onChanged: (value) {
setState(() {
isSwitched = value;
print(isSwitched);
});
},
activeTrackColor: Colors.teal,
activeColor: Colors.white,
)),
]),
Column(children: <Widget>[
isSwitched
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Text(
'NAME:',
style: TextStyle(
color: Colors.teal,
fontSize: 20,
fontWeight: FontWeight.w500),
)),
Container(
child: TextField(
decoration: new InputDecoration(
contentPadding:
const EdgeInsets.all(20.0),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.teal, width: 2.0),
),
hintText: 'Enter NAME'),
),
),
])
: Container(),
])
])),
);
}
}
The output for the above code is as follows:
Before button click
After Button click

Create a new card when FAB is clicked

I need create a card, when the FAB is clicked, like a list or just create a card into Column, like this image:
enter image description here
Here's one way:
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()));
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Widget> cardWidget = [];
buildCard() {
setState(() {
cardWidget.add(
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(),
),
RaisedButton(
onPressed: () {},
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0),
color: Colors.green,
child: Text(
'Criar',
style: TextStyle(
color: Colors.white
),
),
)
],
),
)
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[900],
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.blue[900]
),
floatingActionButton: FloatingActionButton(
onPressed: buildCard,
backgroundColor: Colors.green,
child: Icon(
Icons.add,
color: Colors.white,
),
),
body: Column(
children: cardWidget.map((data) {
return data;
}).toList()
),
);
}
}
This method may not be the best way for you so I encourage you to try something new on your own!

Flutter: is there any possibility to send the button value to the text field?

I am Writing a small quiz game, in which I am pressing the button and these buttons are going to the empty text fields, I don't know how to send the text of the button to the text fields.
here is my code :
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: NinjaCard()));
class NinjaCard extends StatefulWidget {
#override
_NinjaCardState createState() => _NinjaCardState();
}
class _NinjaCardState extends State<NinjaCard> {
String result = "";
String shaka = "";
var text;
String str;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text('Animals'), backgroundColor: Colors.green),
body: Padding(
padding: EdgeInsets.all(15),
child: Column(
children: <Widget>[
Center(
child: Image.asset('lib/photo-1495594059084-33752639b9c3.jpg'),
),
SizedBox(width: 10, height: 10),
Row(children: <Widget>[
Container(
color: Colors.grey,
width: 40.0,
child: Text('$result', style: TextStyle(fontSize: 10.0, height: 2.0, color: Colors.black)),
),
SizedBox(width: 10),
Container(
color: Colors.grey,
width: 40.0,
child: Text('$shaka', style: TextStyle(fontSize: 10.0, height: 2.0, color: Colors.black)),
),
SizedBox(width: 15),
Row(
children: <Widget>[
SizedBox(
width: 50,
child: RaisedButton(
onPressed: () {},
color: Colors.green,
splashColor: Colors.red,
child: Text('S', style: TextStyle(backgroundColor: Colors.green, fontSize: 20, color: Colors.white)),
),
),
SizedBox(width: 15),
SizedBox(
width: 50,
child: RaisedButton(
onPressed: () {},
color: Colors.green,
splashColor: Colors.red,
child: Text('T', style: TextStyle(backgroundColor: Colors.green, fontSize: 20, color: Colors.white)),
),
),
SizedBox(width: 15),
],
),
]),
],
),
),
);
}
}
In a simple case, I would go with a stateful widget and array of letters. Of course, it could be created and sized dynamically, below I only explain the basic idea with some simplifications (no duplicate checks, no shuffling):
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'App',
home: GuessTheWordWidget(),
);
}
}
class GuessTheWordWidget extends StatefulWidget {
#override
_GuessTheWordWidgetState createState() => _GuessTheWordWidgetState();
}
class _GuessTheWordWidgetState extends State<GuessTheWordWidget> {
String _word = 'Goldfish';
List<String> _input = List.generate(8, (_) => '');
int _position = 0;
void _press(int rune) {
setState(() {
if (_position < _input.length) {
print('Position ${_position}, rune: ${String.fromCharCode(rune)}');
_input[_position++] = String.fromCharCode(rune);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('App'),
),
body: Center(
child: Column(children: <Widget>[
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _input
.map((letter) => Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent)),
child: Text(letter),
))
.toList())),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _word.runes
.map((rune) => RaisedButton(
onPressed: () => _press(rune),
child: Text(String.fromCharCode(rune),
style: TextStyle(fontSize: 20)),
))
.toList())),
])),
);
}
}
Go play with this code at DartPad: https://dartpad.dev/69bae58772305c74f1688193076ecaef!

'constraints.hasBoundedWidth': is not true

Following is my code
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Student Info",
debugShowCheckedModeBanner: false,
home: SafeArea(
child: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: ListView(
children: <Widget>[StudentScreenAppBar(), StudentGraduateList()],
),
);
}
}
class StudentScreenAppBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
AppBar(
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: Colors.black,
size: 20.0,
),
onPressed: () {}),
centerTitle: true,
title: Text(
"Student Info",
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
size: 20.0,
color: Colors.black,
),
onPressed: () {}),
// SizedBox(width: 10.0,),
IconButton(
icon: Icon(
Icons.settings_ethernet,
color: Colors.black,
size: 20.0,
),
onPressed: () {})
],
elevation: 0.0,
backgroundColor: Colors.white,
),
Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black)),
padding: const EdgeInsets.fromLTRB(8.0, 2.0, 8.0, 2.0),
child: Image.asset(
"images/isdi_school.png",
width: 40.0,
height: 15.0,
fit: BoxFit.contain,
))
],
);
}
}
class StudentGraduateList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
yearListForUgPg("Under Graduate"),
yearListForUgPg("Post Graduate")
],
),
);
}
Widget yearListForUgPg(String graduationName) {
return Column(
children: <Widget>[
Container(
padding: const EdgeInsets.fromLTRB(25.0, 4.0, 25.0, 4.0),
child: Text(
graduationName,
style:
TextStyle(color: Colors.white, fontFamily: "suisseintlMedium"),
),
decoration: BoxDecoration(color: Colors.black),
),
ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"2018",
style: TextStyle(
fontFamily: "okomitoBold", color: Colors.black),
),
Icon(Icons.arrow_forward)
],
);
},
itemCount: 10,
)
],
);
}
}
The ListView Widget does not get displayed. If I comment the ListView then the code works fine and I am able to see the UI. I tried wrapping the ListView in Expanded and Flexible Widget but it does not work.
If I uncomment the ListView then I get error saying 'constraints.hasBoundedWidth': is not true. I am trying to achieve something like this in my UI:
![Image][1]
Simply wrap your -Column in Expanded Widget: that way your Column will try to occupy available space in the parent Row.
Updated code:
class StudentGraduateList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(child: yearListForUgPg("Under Graduate")),
Expanded(child: yearListForUgPg("Post Graduate"))
],
),
);
}