How can I make the table take the available space along the height? - flutter

I have the following table
#override
Widget build(BuildContext context){
final TheGroupPageArguments arguments = ModalRoute.of(context).settings.arguments;
return Scaffold(
body: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
children: [
Flexible(
flex: 1,
child: Align(
alignment: Alignment.center,
child: DigitalSpeedMeter(),
),
),
Flexible(
flex: 6,
child: Table(
children: [
TableRow(children: [backButton(), backButton(), backButton()]),
TableRow(children: [backButton(), backButton(), backButton()]),
],
),
),
]
),
),
);
}
But it only takes half the screen height. How can I make it strecht to it's parent's height?
This is how it looks now
This is what it should look like
This is what it should look like

You can use the "Expanded" instead of "Flexible".

I can't find a good solution.
Anyone know a good way?
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
children: [
Expanded(
flex: 1,
child: Container(
color: Colors.yellow,
child: Align(
alignment: Alignment.center,
child: Text(
'0\nMPH',
textAlign: TextAlign.center,
),
),
),
),
Expanded(
flex: 6,
child: Column(
children: [
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: FlatButton(
onPressed: () {},
color: Colors.tealAccent,
child: Text("button1"),
),
),
Expanded(
child: FlatButton(
onPressed: () {},
color: Colors.green,
child: Text("button2"),
),
),
],
),
),
Expanded(
child: Container(
color: Colors.grey,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: FlatButton(
onPressed: () {},
color: Colors.blue,
child: Text("button3"),
),
),
Expanded(
child: FlatButton(
onPressed: () {},
color: Colors.amber,
child: Text("button4"),
),
),
],
),
),
),
],
),
),
],
),
),
);
}

I found a solution. How about this?
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.all(20.0),
child: Column(children: [
Flexible(
flex: 1,
child: Align(
alignment: Alignment.center,
child: Container(
color: Colors.yellow,
child: Align(
alignment: Alignment.center,
child: Text(
'0\nMPH',
textAlign: TextAlign.center,
),
),
),
),
),
Flexible(
flex: 6,
child: Table(
children: [
TableRow(children: [backButton(), backButton(), backButton()]),
TableRow(children: [backButton(), backButton(), backButton()]),
],
),
),
]),
),
);
}
Widget backButton() {
return Container(
height: MediaQuery.of(context).size.height / 7 * 6 / 2 - 7,
child: FlatButton(
onPressed: () {},
color: Colors.tealAccent,
child: Text("button"),
),
);
}

I ended up doing the following. A widget that makes the rows and columns dynamically based on the the widgets put into it.
import 'package:flutter/material.dart';
class ExpandingGrid extends StatelessWidget {
final List<Widget> tiles;
final int columns;
const ExpandingGrid({this.tiles, this.columns});
int _rows(){
return (tiles.length / columns).ceil();
}
int _tileIndex(int row, int column) => row * columns + column;
Widget _gridTile(int row, int column){
if(_tileIndex(row, column) < tiles.length)
{
return Expanded(
child: tiles[_tileIndex(row, column)],
);
}
return Spacer();
}
#override
Widget build(BuildContext context) {
return Column(
children:
[
for(int r = 0; r < _rows(); r++ )
Expanded(
child: Row
(
children :
[
for(int c = 0; c < columns; c++)
_gridTile(r, c),
]
),
)
]
);
}
}

Related

Flutter - How to make the first element of a dynamic list fixed (unscrollable) at top?

PopupMenuButton<String>(
///Icon
child: SizedBox(
child: Stack(
children: [
const Icon(
Icons.notifications_outlined,
),
Container(
child: Container(
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Center(
child: Text(
''
),
),
),
),
)
],
),
),
onSelected: (value) {},
itemBuilder: (BuildContext context) {
///generating list on the fly
var myList = someList!.map((listItem) {
return PopupMenuItem<String>(
value: listItem.id.toString(),
child: SizedBox(
child: Column(
children: [
Text(
listItem.name!,
),
],
),
),
);
}).toList();
var closeButtonList = [
PopupMenuItem<String>(
child: Column(
children: [
Align(
alignment: Alignment.centerRight,
child: IconButton(
onPressed: Navigator.of(context).pop,
icon: const Icon(
Icons.close,
),
),
),
],
),
),
///appending list using spread operator
...myList
];
return closeButtonList;
},
This code works fine and displays a cross(close) icon as the first element of the list.
The problem is when I scroll the list, the icon get scrolled and disappears from the screen.
How can I make it fixed while the rest of the list is scrollable?

Bottom overflow 13 pixels

How can fix it?
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
fit: StackFit.loose,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
flex: 2,
child: buildSearch(),
),
Expanded(
flex: 2,
child: Container(color: Colors.green),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Frequitly Visited'),
TextButton(
onPressed: () {},
child: Text('Show More'),
),
],
),
Expanded(
flex: 6,
child: buildSites(size),
)
],
)
],
),
);
}
buildSearch() {
return Container(
child: FloatingSearchBar(
transitionCurve: Curves.easeInOutCubic,
transition: CircularFloatingSearchBarTransition(),
physics: const BouncingScrollPhysics(),
scrollPadding: EdgeInsets.zero,
builder: (context, _) => _history(),
),
);
}
Container buildSites(size) {
return Container(
color: Colors.black,
width: size.width,
);
}
Widget _history() {
List<String> listHistory = [
'Flutter',
'Python',
'Nodejs',
'Rails',
];
return ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Material(
child: Column(
children: listHistory
.map((e) => ListTile(
title: Text(e),
onTap: () {},
))
.toList(),
),
),
);
}
}
try to fixed the height of search & container, expanded only flexible part:
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 100,
child: buildSearch(),
),
Container(
height: 100,
child: Container(color: Colors.green),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Frequitly Visited'),
TextButton(
onPressed: () {},
child: Text('Show More'),
),
],
),
Expanded(
child: buildSites(size),
)
],
)
You can just remove the Expanded widget wrapped around your buildSearch() widget and give a desired padding or you can also your sizedbox with a desiredHeight below and above the buildSearch()
so basically change
...
Expanded(
flex: 2,
child: buildSearch(),
),
...
to
...
Padding(
padding:EdgeInsets.only(top:20,bottom:50), // adding a suitable padding should fix it
child:buildSearch(),
)
...

How to make image layout inside card like this?

I receive a list of images from api call, I need to layout these images like on this example, I have already implemented this logic, but I think it is redundant, and can be done easier, without hard-coded which item need to be first, last, etc.. and I think that widget tree could be less. How I can improve this code?
my emplementation:
List<Widget> _listImages() {
List<Widget> imagesList = [];
for (int i = 0; i < images.length; i++) {
imagesList.add(
Expanded(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: GestureDetector(
onTap: () {
open(context);
},
child: child: NetworkImage(images[i]),
),
),
);
);
}
return imagesList;
}
Widget build(BuildContext context) {
return Card(...
Column(//Image layout
children: [
Row(
children: [
_listImages().first,
],
),
Container(
height: 110,
child: Row(
children: [
Expanded(
flex: 2,
child: Row(
children: _listImages().getRange(1, 3).toList(),
),
),
Expanded(
child: Stack(children: [
Row(
children: [
_listImages().elementAt(3),
],
),
IgnorePointer(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
color: Colors.black54,
child: Center(
child: Text(
'+ ${_listImages().length - 3}',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.w500),
),
),
),
),
),
]),
),
],
),
),
],
)
....
}
You could try Gridview. You can use main axis spacing and cross axis spacing to change the distance between grid tiles.
https://www.geeksforgeeks.org/flutter-gridview/

Flutter adding dynamic row tables in between static rows, with different background color

I am trying to show a dynamic table,
Following is the code i am using
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: isAPICall
? spinner()
: ListView.builder(
itemCount: reportList.length,
itemBuilder: (context, index) {
return reportListData(index);
}));
}
Widget reportListData(int propertyIndex) {
Data data = reportList[propertyIndex];
return GestureDetector(
child: SingleChildScrollView(
child: Center(
child:
Column(mainAxisSize: MainAxisSize.max, children: <Widget>[
Container(
color: Colors.white,
padding: EdgeInsets.fromLTRB(20.0, 0, 20.0, 0),
child: Table(
border: TableBorder.all(color: Colors.black),
columnWidths: {
0: FractionColumnWidth(.25),
0: FractionColumnWidth(.25),
0: FractionColumnWidth(.25),
0: FractionColumnWidth(.25),
},
children: [
TableRow(children: [
Container(
padding: EdgeInsets.all(10.0), child: Text(data.level)),
Container(
padding: EdgeInsets.all(10.0),
child: Text(data.recievedAmt.toString())),
Container(
padding: EdgeInsets.all(10.0),
child: Text(data.pendingAmt.toString())),
Container(
padding: EdgeInsets.all(10.0),
child: Text(data.totalAmt.toString())),
]),
])),
]))));
}
}
Here i want to add a header and footer rows.
Header rows is telling the title of each column whereas footer row will be have two columns.
how to add the header and footer in the code
in the same way,
if there is no data, need to show text "No Data" with header
2.i need to add alternative background color for the rows like white and grey -
code sample :
class RadioTest extends StatefulWidget {
#override
_RadioTestState createState() => _RadioTestState();
}
class _RadioTestState extends State<RadioTest> {
ScrollController _scrollController;
List<String> list;
#override
void initState() {
super.initState();
_scrollController = ScrollController()
..addListener(() {
print("offset = ${_scrollController.offset}");
});
list = List<String>();
for (var i = 0; i < 10; i++) {
list.add(i.toString());
}
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Table(
children: [
TableRow(
children: [
TableCell(
child: Text("level"),
),
TableCell(
child: Text("number 0 "),
),
TableCell(
child: Text("number 1 "),
),
TableCell(
child: Text("number 2 "),
),
],
),
if (list.isNotEmpty)
...list.map(
(item) => TableRow(
children: [
TableCell(
child: Center(
child: Text("level-$item"),
),
),
TableCell(
child: Center(
child: Text("-"),
),
),
TableCell(
child: Center(
child: Text("-"),
),
),
TableCell(
child: Center(
child: Text("-"),
),
),
],
),
),
TableRow(
children: [
TableCell(
child: Text("footer"),
),
TableCell(
child: Text("number 0 "),
),
TableCell(
child: Text("number 1 "),
),
TableCell(
child: Text("number 2 "),
),
],
),
],
),
);
}
}
I just did it with some dummy data and put some cases on the data status if its not empty build table row otherwise dont do it .
hope it helped you good luck

Flutter invalid refrence to 'this' expression

i am trying to add item in list when i click on add button, all code is ok, but i am getting error invalid reference to this expression. i am using stateful widget.
List<Widget> _listSection = [];
body: Container(
child: Stack(
children: [
FloatingActionButton(
onPressed: () {
_listSection.add(
listSectionMethod(
"title three", "hello from click", Icons.forward),
);
setState(() {});
},
),
],
),
),
),
);
}
}
Widget listSection = Container(
margin: EdgeInsets.only(top: 210),
child: ListView(
children: [
Column(
children: [
Column(
children: this._listSection, // ----> ERROR HERE
),
],
),
],
),
);
List Section Method:
Card listSectionMethod(String title, String subtitle, IconData icon) {
return new Card(
child: ListTile(
title: Text(
title,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(subtitle),
trailing: Icon(
icon,
color: Colors.blue,
),
),
);
}
change this:
Widget listSection = Container(
margin: EdgeInsets.only(top: 210),
child: ListView(
children: [
Column(
children: [
Column(
children: this._listSection,
),
],
),
],
),
);
for this:
Widget listSection() {
return Container(
margin: EdgeInsets.only(top: 210),
child: ListView(
children: [
Column(
children: this._listSection,
),
],
),
);
}