ListView - Card (Flutter Layout) - dart

Flutters!
I need to recreate this layout in Flutter to be displayed as items in a ListView.
Both layouts (Emma & Tonny) are the same.. the only difference is the colors that depend on some other data/status, something that I will decide programmatically later.
I already have the ListView.builder as follow:
ListView.builder(
itemCount: WeeklyList.contacts.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () => onTapMe(WeeklyList.contacts[index]),
child: TripItemCard(index, WeeklyList.contacts[index]));
})
and.... the main missing guy:
Widget TripItemCard(int index, Info info) {
return SizedBox(
height: 116,
child: Card(
//.... Card Layout.....
)
);
NOTE: I wrapped the Card with a SizedBox to be able to have a Height specified for all cards.
There are 8 widgets in total:
1- The Card
2- Picture
3- Fullname
4- Role
5- PickUp Label
6- PickUp Time
7- DropOff Label
8- DropOff Time
Lastly and Very Important Things
1- Please be advised that there are 2 TEXTs (Name and DropOff Status) who have BACKGROUND and TEXT color... and both of them... fully expanded (width). This is very important to maintain the horizontal color balance.
2- Also PickUp and DropOff are aligned to the right where the PickUp and DropOff Time/Status respectively are aligned to the left.
PLEASE.Help();
thanks.dart

The basic layout should look like this and you can add the details to it.
Row(children: [
Image.asset(name),
Column(
children: [
Container(
color: const color,
child: const Text(data),
),
Text(data),
Text(data),
Text(data),
],
),],),

Related

If in Flutter Expanded is written in Column on iPhone 14 Pro Max, it continues indefinitely. why?

How One UI looks on iPhone 14 Pro Max and other phones.
The code written in Flutter is as follows:
return SafeArea(
child: SmartRefresher(
controller: controller.balanceRefreshController,
onRefresh: () => controller.onRefreshBalance(),
child: Padding(
padding: EdgeInsets.all(AppPaddings.side),
child: Column(
children: [
// #Balance
_getBalanceWidget(controller),
// #choose amount
Expanded(child: _getChooseAmountWidget(controller)),
// #button
_getActivatedDefaultButton(controller),
],
),
),
));
With BalanceWidget, the remaining space allocated to the button should have been left to _getChooseAmountWidget.
But why didn't it happen?
(I know how to show button in UI. For example I can use Stack. I wonder why the code doesn't work properly, not show the button)
Some cases:
If _getChooseAmountWidget has 4 items:
If I remove Expanded:
// #Balance
_getBalanceWidget(controller),
// #choose amount
// Expanded(child: _getChooseAmountWidget(controller)),
// #button
ActivatedDefaultButton(
isActive: controller.selectedItem != null,...

Laying out widgets from the corners and grow one with window

I’d like to place
an unspecified number of Text widgets from top-left to bottom
3 TextButton widgets from bottom-right to left and
a random parent content widget top-right
The Text and TextButton widgets should only take their minimum space while the the content widget should expand to bottom-left (upon windows resizing) with its children centered like so.
Maybe I’m just unlucky or misled/spoiled by Qt’s QSpacerItem…?
This is a desktop App so “windows resizing” really makes sense in flutter context! ;)
Also, more generally, is there a way to directly nest (some kind of) Row/Column instances and stretch Widgets down/right?
You'll want to use a combination of Row, Column and Expanded to achieve this effect.
I'm going to assume that the bottom left corner belongs to the left-hand side bar. With that in mind, your basic structure can look something like this:
Row(
children: [
// Side bar
SizedBox(
width: 250,
ListView.builder(
// Display text widgets
),
),
// This widget will fill whatever space remains in the Row after the side bar
Expanded(
child: Column(
children: [
// This widget will fill all the space before the footer
const Expanded(
child: Center(
child: Text("Resizable Window"),
),
),
// Footer with buttons
SizedBox(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// Your buttons
]
),
),
],
),
),
],
)
Full example on DartPad

Is there a more optimal way to space widgets within a column?

So i'm emulating an old app I have where the UI looks like this
Currently i'm focused on creating the UI layout for the purple side bar, I did that by creating a Container with a purple background. Within the container I created a column with multiple children and just used an empty SizedBox to create distance between one widget from another.
import 'package:flutter/material.dart';
class SignInPage extends StatelessWidget {
const SignInPage({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Sample Text'),
// elevation: 5.0,
// ),
body: _buildContent(),
);
}
Widget _buildContent() {
// private method
return Container(
color: Colors.deepPurpleAccent,
padding: EdgeInsets.all(16.0),
child: Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
color: Colors.orange,
child: SizedBox(
height: 100.0,
width: 80.0,
),
),
SizedBox(
height: 140.0,
),
Container(
color: Colors.red,
child: SizedBox(
height: 50.0,
width: 80.0,
),
),
SizedBox(
height: 8.0,
),
Container(
color: Colors.purple,
child: SizedBox(
height: 50.0,
width: 80.0,
),
),
],
),
);
}
}
I'm quite new to flutter so i'm wondering if there's a better way to structure my layout of the side bar? Also to think in the future, since the name "BagTrack" Is on the same level as "Analytic Overview" Should that just be one giant row"?
Actual answer
Method 1
#Mahfuzur Rahman answer is good, but to actually answer your question about other ways. Flex widgets (Column and Row extend the Flex widget), have both mainAxisAlignment and crossAxisAlignment, they can be used to align them more easily between different devices/screens sizes.
So maybe grouping your red and purple boxes in a Column with mainAxisSize set to MainAxisSize.min, and aligning the surrounding column with a specific size.
https://api.flutter.dev/flutter/widgets/Column-class.html
Method 2
Another way, if you would like some widget to occupy some percentage amount of space from it's parent, I suggest you look into Expanded widget, Flexible widget.
Method 3
Or even FractionallySizedBox could be a good widget for you, but then I would also look at this LayoutBuilder widget to solve the potential Unbounded Height/Width exception.
Second smaller question
It's entirely up to you to decide about your second question concerning the giant row. I wouldn't do it though. Probably would use a const SizedBox or const EdgeInsets (for Padding) and keep them at the same height this way.
Just complementing Flutter knowledge
PS: Since you are new to Flutter. As a suggestion for future performance: avoid the Container widget as much as you know, there are a lot of simpler widgets like SizedBox, ColoredBox, DecoratedBox and Padding that you can use in its place that could be marked as const sometimes and be less expensive.
For understanding final and const:
final is a variable that cannot be reassigned by accident inside your code. When you instantiate it you give it a value and that's it. (Using late changes that a bit but not much);
const is a variable assigned by the compiler, if you are familiar with C it's like #define but there is a little difference, every time you say const EdgeInsets.all(8) for example, the compiler will detect that and use the same variable, so you don't have to remember a specific constant variable name.
Yes there is. But using SizedBox also wont hurt.
I usually Prefer ListTile for each element in the drawer.
ListTile(
leading: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {},
child: Container(
width: 48,
height: 48,
padding: const EdgeInsets.symmetric(vertical: 4.0),
alignment: Alignment.center,
child: const CircleAvatar(),
),
),
title: const Text('title'),
dense: false,
)

After flutter Upgrade Listtile leading content does not match parent anymore

After doing flutter upgrade yesterday the content of ListTile leading (especially the height) does not match parent anymore.
I have a overflow in height now. Width is working as expected.
As you can see in the picture there is still space below the leading widget.
Does anyone know how to fix this?
Or is there a way to downgrade the flutter version?
Widget _listTile(){
return ListTile(
contentPadding: EdgeInsets.fromLTRB(3.0, 1.0, 0.0, 1.0),
dense: true,
leading: Column(
children: <Widget>[
_leadingButton(),
_leadingProgress
],
),
title: _textSubtitle(subtitle),
subtitle: _textSubtitle(subtitle),
);
}
I believe the change that has caused this is [this one][1]: https://github.com/flutter/flutter/commit/0e2eeb5a485aaccdab7007ad9b90fd8120e77983#diff-53f33273ae4e7462729c5f4b7394428b. If you read the code, it says it was doing an update to adhere to the material spec which means a constraint on the size of the widget, so there's a very good chance it won't change back to how it was. How you were using it was technically against the material spec.
But rather than trying to downgrade flutter, you could simply create your own widget that does the same thing - you don't need to use a ListTile.
Something like this would probably do:
class MyListTile extends StatelessWidget {
final Widget leading;
final Widget title;
final Widget subtitle;
final EdgeInsets padding;
MyListTile({#required this.leading, #required this.title, #required this.subtitle, this.padding});
#override
void build(BuildContext context) {
return Padding(
padding: padding ?? EdgeInsets.zero,
child: Row(
children: [
leading,
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
title,
subtitle,
],
),
),
],
),
);
}
}
Full disclosure though - I haven't run that code or even put it in an IDE so it may have issues, but that should illustrate the basics of what you're trying to do there. You'd probably want to wrap things in padding (most likely at least the leading widget) as needed to get the spacing you currently have.

PageView.builder giving Horizontal viewport was given unbounded height error

I'm very new to flutter and I'm trying to learn how to create views. I tried to create a separate file of the view, or widget if that's what it's called in flutter, and just call it from the main.dart.
I have a separate widget containing this code
class PageEntryWidgetMain extends StatefulWidget {
final PageViewEntryMain pageViewEntryMain;
const PageEntryWidgetMain({Key key, this.pageViewEntryMain})
: super(key: key);
#override
State<StatefulWidget> createState() {
return _PageEntryWidgetMainState();
}
}
class _PageEntryWidgetMainState extends State<PageEntryWidgetMain> {
#override
Widget build(BuildContext context) {
return Container(
child: Row(
children: <Widget>[
Text(widget.pageViewEntryMain.title)
],
),
);
}
}
and I'm trying to show it by using a view pager with the following code
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
PageView.builder(
itemBuilder: (context, position) {
PageEntryWidgetMain(
pageViewEntryMain: pages[position],
);
},
itemCount: pages.length,
scrollDirection: Axis.horizontal,
)
],
),
),
);
but it gives me the following errors
Horizontal viewport was given unbounded height.
Viewports expand in the cross axis to fill their container and constrain their children to match their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of vertical space in which to expand.
I'm a little confused at what it's actually complaining of. I am able to display just one view, by replacing the PageView.builder with this code
PageEntryWidgetMain(pageViewEntryMain: pages[0])
So I believe that the separate widget, in itself, does not have a problem. It's probably about how I am trying to use the ViewPager that's giving me errors.
I have been searching for PageView implementations but I have not seen one that actually has a separate view to just call for displaying. I need to learn it this way so I would be able to separate the views instead of just writing it all in one file.
PageView cannot be the direct child of Column. Change your column to add an Expanded between the two, as below:
Column(
children: <Widget>[
Expanded(
child: PageView.builder(),
),
]
)
To explain what's going on here, Column has an unbounded horizontal width, ie it'll keep expanding horizontally to take as much space as it's child needs. PageView (and any other horizontally scrolling widget) requires horizontal constraints for the scroll logic to work.
Expanded restricts the horizontal size of the PageView by taking up as much space as possible, which should solve the issue.
You can use any Widget that has a fixed height and width to wrap the PageView.
For example, I use Container():
Column(
children: <Widget>[
Container(
width: double.infinity,
height: 100.0,
child: PageView.builder(),
),
]
)

Resources