return Scaffold(
body: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
color: Colors.red,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: SelectGroupCard(context, titles: titles, ids: ids,
onTap: (title, id) {
setState(() {
cardGroupResult = title + " " + id;
});
}),
),
),
],
),
There are several cards as seen in the picture. I want to get these right out. I even want to be able to show these cards in the middle of the page, in 3 columns, 4 rows.
Use widget GridView, it allows you to select the desired number of columns and rows. Also, it is possible to install paddings.
you can use GridView
GridView(
gridDelegate:const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // you can change this
),
children :[...] // put your cards here !
)
you can remove the width property of SelectGroupCard. for example, if SelectGroupCard is a row widget, the following code like this:
Row(
mainAxisSize: MainAxisSize.min,
children: [],
)
Related
I am rendering a standard Table inside a GridView, inside a Flex inside a Row. The 2nd row of the table includes a Button.
When the contents of the first row of the table are above a certain size the clickable region of the button begins to cut off, missing entirely over a certain size.
Note: this is using Flutter Web, I have not tested on Mobile/Desktop.
I have created a minimal reproducible example in an attempt to isolate all logic.
Widget _render() {
return Row(mainAxisSize: MainAxisSize.max, children: [
SizedBox(
width: 900,
height: 900,
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Table(border: TableBorder.all(), children: <TableRow>[
TableRow(
children: <Widget>[
TableCell(
child: Text(''),
),
TableCell(
child: SizedBox(
height:
440, //The clickable region of the button begins to be cut off around 430, and stops altogether by 450
))
],
),
TableRow(children: <Widget>[
TableCell(
child: Text(""),
),
TableCell(
child: TextButton(
onPressed: () => {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Hi Button"))),
},
child: Text("Hi"))),
])
]),
],
),
),
]);
}
What is causing this effect? I am assuming it is some interaction between the visible container and the Table.
Edit: as suggested by #pskink rendered with debugPaintSizEnabled flag which highlights the problem perfectly. However; how would you fix?
I created onboarding in my flutter app:
This is my data model:
class Data {
final String image;
final String title;
final String desc;
Data(this.image, this.title, this.desc); }
final List<Data> items = [
Data('assets/1.png', '1', '1'),
Data('assets/2.png', '2', '2'),
Data('assets/3.png', '3', '3')
];
This is my code:
Scaffold(
body: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
PageView.builder(
controller: _pageController,
itemBuilder: (BuildContext context, int index) {
var item = items[index];
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(item.image),
fit: BoxFit.cover,
),
),
//bloc1
child: Padding(
padding: const EdgeInsets.only(bottom: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text(item.title), Text(item.desc)],
),
),
);
},
),
//bloc 2
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Padding(
padding: EdgeInsets.only(bottom: 10, top: 10),
child: Text('****dots indicators****'),
),
TextButton(
onPressed: () {},
child: Text('Next'),
)
],
))
],
),
);
This onBoading consists of three parts:
background image
text block - block1
"lower action block" - block2.
I need to have a small fixed distance between blocks 1 and 2 - 10pх.
but also I can't place block1 and block2 together. I need block1 to be "inside" PageView, block2 on the main page.
right now I'm using the bottom padding. but this is not a reliable solution - this size may change on different screens - "overlapping" will occur.
how can I fix this problem? Any advice - I'll be very grateful.
If you want to position your "page indicator dots" at a fixed relative spot, for example, 10% from the bottom of the screen, an easy solution is to use the Align widget.
However in your case, you must also change the Column in your to MainAxisSize.min, so that its height will be as small as possible, leaving you enough freedom to decide where to position the Column vertically. For example:
SafeArea(
child: Align(
alignment: Alignment(0, 0.95), // relative position
child: Column(
mainAxisSize: MainAxisSize.min, // make Column shorter
children: [
Text('****dots indicators****'),
TextButton(
onPressed: () {},
child: Text('Next'),
)
],
),
),
),
For the alignment property of the Align widget, the values are (x, y) ranging from -1 to +1, with 0 being the center. For example, you can use alignment: Alignment(0, -0.5) to make it center horizontally, and 50% towards the top on the vertical axis.
I am trying to get the layout as in the gif below but could not get any resource to continue with. There are two rows with multiple columns and is scrollable. How can I achieve such layout?
As your question says, you follow this approach, and it is not containing multiple columns, items are having different width. This snippet will work fine.
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
children: [
Row(
key: const ValueKey("row1"),
children: _items(),
),
Row(
key: const ValueKey("row2"),
children: _items(),
),
],
),
),
You can achieve this by SingleChildScrolView widget with axis : horizontal and that listitem will be created using FilterChip widget.
like this :
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Wrap(
spacing: 10.0,
runSpacing: 5.0,
children: [...generateTags()],
),
),
generateTags(){
return _keywords.map((e) => FilterChip(label : e)).toList();
}
var _keywords =["hello" , "hi" ,"words 1" , "word 2"];
I have a SingleChildScrollView and inside it I have a list with some cards, that you can remove ou add more. I need to fix an add button at the bottom of the screen, when the card list is not scrollable yet, but when the card list increase size and the scrollview is able to scroll now (to see all the content), the button must follow the list and not keep fixed at the bottom anymore.
For now, what I did to solve this, was check the scroll view every time that a card is added ou removed, if I checked that the screen is now scrollable or not scrollable I change some properties of my build widget:
SingleChildScrollView(
controller: _scrollController,
physics: AlwaysScrollableScrollPhysics(),
child: Container(
height: isNotScrollable
? _pageSize - (_appBarSize + _notifySize)
: null,
padding: const EdgeInsets.symmetric(
horizontal: Constraints.paddingNormal),
child: Column(
.....
and after the list render I create the button like this
isNotScrollable
? Expanded(
child: Container(),
)
: Container(),
CVButton(
color: Palette.white,
Basically, my idea is: if the screen is not scrollable yet (the list content fits in the screen size) I will set a height to the container inside scrollview and add a Expanded() widget before the add button (so the button will stay in the bottom of the container), but if the screen is scrollable (the list content not fits inside the screen size) so I remove the container height and the Expanded widget, then the button will follow the list now as normally.
I don't know if this is the better way to deal with that, I want to know if there is some way to do this without this 'dinamic' way that I am doing, only with fixed widgets and not changing the widget according to the state of the scrollview.
An example when the list becomes scrollable and the button will keep at list bottom
Here the list is not scrollable yet but the button must be at the screen bottom and not list bottom
(I dont wanna use bottomNavBar)
Anyone has any idea how I can solve this?
I have a solution for this. check the code bellow. I added some buttons to add or remove cards. The main trick is to use constraints like minHeight.
import 'package:flutter/material.dart';
class BottomButton extends StatefulWidget {
#override
_BottomButtonState createState() => _BottomButtonState();
}
class _BottomButtonState extends State<BottomButton> {
List<Widget> cards = [];
#override
Widget build(BuildContext context) {
var appBar2 = AppBar(
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
_addCard();
}),
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
_removeCard();
}),
],
);
return Scaffold(
appBar: appBar2,
body: Container(
height: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top + appBar2.preferredSize.height),
alignment: Alignment.topCenter,
child: ListView(
primary: true,
children: [
Container(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top +
appBar2.preferredSize.height),
),
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top +
appBar2.preferredSize.height +
50),
),
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: cards,
),
),
ElevatedButton(
child: Text('this is a button'),
onPressed: () {},
),
],
),
)
],
),
),
);
}
void _addCard() {
Widget card = Card(
child: Container(
height: 100,
color: Colors.red,
padding: EdgeInsets.all(2),
),
);
setState(() {
cards.add(card);
});
}
void _removeCard() {
setState(() {
cards.removeLast();
});
}
}
I have an image and I want to create a row of 5 copies of that image. The simplest way I see of doing that is the following:
Row(
children: <Widget>[
Expanded(
child: Image.asset('images/penny.png'),
),
Expanded(
child: Image.asset('images/penny.png'),
),
Expanded(
child: Image.asset('images/penny.png'),
),
Expanded(
child: Image.asset('images/penny.png'),
),
Expanded(
child: Image.asset('images/penny.png'),
),
],
),
However, this approach is obviously incredibly repetitive. I could write a function for the Expanded widget to make it look a little cleaner, but is there a better approach that is less repetitive and will allow me to easily control how many duplicate images I can create?
Container(
child: Row(
children: List.generate(
5,
(index) => Expanded(
child:
Image.asset('assets/yourImage'))),
))
I found a way of doing it with GridView, so I think I'll use this, as it'll also be useful later when I want to create more pennies. (Like for 100 pennies, I would want to display them in several rows and not just one.)
GridView.count(
crossAxisCount: 5 ,
children: List.generate(5,(index){
return Container(
child: Image.asset('images/penny.png'),
);
}),
)
To make this even more customizable:
GridView build2DArrayOfPennies(int rowCount, int numItems, String imageFile) {
return GridView.count(
crossAxisCount: rowCount,
children: List.generate(numItems,(index){
return Container(
child: Image.asset(imageFile),
);
}),
);