how to add a row on top of listview - android

i am very new in flutter, i have a list of rows which are part of a listview that contain strings from lists and i want to add a seperate header on top of the listview in order to put a different content,but i keep getting errors cause the listview is combined with a futureBuilder, what sort of code should i add?
`body: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Container(
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
child: Container(
width: double.infinity,
padding: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_sell[index]["text"],
style: TextStyle(fontSize: 20),
),
Text(
(snapshot.data.sellprice[index]).toString(),
style: TextStyle(fontSize: 20,color:Colors.grey),
),
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_buy[index]["text"],
style: TextStyle(fontSize: 20),
),
Text(
_buy[index]["symbol"],
style: TextStyle(
fontSize: 20, color: Colors.grey),
),
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_currency[index]["text"],
style: TextStyle(fontSize: 17),
),
Text(
_currency[index]["symbol"],
style: TextStyle(
fontSize: 17, color: Colors.grey),
),
],
),
),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset(
_picture[index],
height: 50,
width: 50,
),
],
),
),
],
),
),);
},
itemCount: 7),
`

lets say your header widget is of type HeaderWidget (could be another Container or a Row or a custom widget). Then you have to ask yourself the following question: Does the header disappear when i scroll far enough in the listview or does it always stay on top?
Scrollable:
ListView.builder(
itemBuilder: (context, i) => i < 1 ? HeaderWidget() : buildChild(i-1),
itemCount: 7,
)
Non-scrollable / fixed:
Column(
children: <Widget>[
HeaderWidget(),
ListView.builder(
itemBuilder: (context, i) => buildChild(i),
itemCount: 7,
),
],
)

Try something like:
body: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Container(
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
child: Container(
width: double.infinity,
padding: EdgeInsets.all(5),
child: _content(index),
),);
},
itemCount: 7),
}
}
_content(index){
if(index == 0){
return /*Different header*/
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_sell[index]["text"],
style: TextStyle(fontSize: 20),
),
Text(
(snapshot.data.sellprice[index]).toString(),
style: TextStyle(fontSize: 20,color:Colors.grey),
),
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_buy[index]["text"],
style: TextStyle(fontSize: 20),
),
Text(
_buy[index]["symbol"],
style: TextStyle(
fontSize: 20, color: Colors.grey),
),
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
_currency[index]["text"],
style: TextStyle(fontSize: 17),
),
Text(
_currency[index]["symbol"],
style: TextStyle(
fontSize: 17, color: Colors.grey),
),
],
),
),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset(
_picture[index],
height: 50,
width: 50,
),
],
),
),
],
),
}
}

What worked for me was wrapping the ListView and the header in a column. I order to make the ListView cover the remaining height, wrap it in an Expanded widget as shown below:
Column(
children: <Widget>[
Text("Header Title")
Expanded(
child: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index){
return (
Container()
)
}
)
),
],
)

Related

Why cant i add Listview to Flutter ? (The relevant error-causing widget was Column)

When I try to add listview, its always gives me errors. Like:
RenderBox was not laid out: RenderRepaintBoundary#dab18 NEEDS-LAYOUT NEEDS-PAINT
Failed assertion: line 1982 pos 12 : 'hasSize'
The relevant error-causing widget was Column
I tried to add shrinkwrap to listview but it doesn't work too. When I delete my listview its works fine but I need to add it. What am I making wrong? Thanks for all your help! My code :
SliverToBoxAdapter(
child: Container(
child: Column(children: [
Container(
width: double.infinity,
child: Stack(
children: [
CorneredImage(
child: Image(
image: AssetImage(
'assets/images/phone-call.png',
),
),
),
Positioned.fill(
child: Container(
decoration: //some decors
),
),
Positioned.fill(
child: Container(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.all(24),
child: FractionallySizedBox(
widthFactor: 0.7,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: Column(
children: [
Text(
"Dilediğiniz Yerden Bağlanın!",
),
SizedBox(height: 10),
Text(
"Terapizone, ihtiyacınız olduğu her an size destek olmak için yanınızda!",
),
],
),
),
Align(
alignment: Alignment.bottomLeft,
child: ElevatedButton(
onPressed: () {},
child: Text("Terapiye Başla"),
)
],
),
),
),
),
)
],
),
),
Flexible( //When I add that part its not working anymore. List is simple String list
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) => Text(list[index]))),
]),
),
),
Try This,
CustomScrollView( // Wrap SliverToBoxAdapter with CustomScrollView
shrinkWrap: true,
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
child: Column(mainAxisSize: MainAxisSize.min, // give mainAxixsize
children: [
Container(
width: double.infinity,
child: Stack(
children: [
Image(
image: AssetImage(
'assets/images/phone-call.png',
),
),
Positioned.fill(
child: Container(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.all(24),
child: FractionallySizedBox(
widthFactor: 0.7,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Column(
children: [
Text(
"Dilediğiniz Yerden Bağlann!",
),
SizedBox(height: 10),
Text(
"Terapizone, ihtiyacnz olduğu her an size destek olmak için yannzda!",
),
],
),
),
Align(
alignment: Alignment.bottomLeft,
child: ElevatedButton(
onPressed: () {},
child: Text("Terapiye Başla"),
))
],
),
),
),
),
)
],
),
),
Flexible( //When I add that part its not working anymore. List is simple String list
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) => Text(list[index]))),
]),
),
),
// SizedBox(height: 1) // <-- Divider
],
)

setState() called after dispose(): _StatefulBuilderState#09642(lifecycle state: defunct, not mounted)

I'm showing content with bottomsheet, i'm updating folder size after calculating it, using statefulbuilder's setState, i used mounted condition also, then also it showing setState after called dispose, Help me to solve this.
FileStat fileStat = selectedFilesAndFolders.last.statSync();
String size = '0 KB';
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.0),
topRight: Radius.circular(12.0),
)),
builder: (context) {
return StatefulBuilder(builder: (context, newSetState) {
getFolderSize(selectedFilesAndFolders.last.path).then((value) {
if (!mounted) return;
newSetState(() {
size = value;
});
});
return SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 2.0,
),
Text(
'Info',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 2.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text('Name: '))),
Expanded(
child: Text(path
.basename(selectedFilesAndFolders.last.path)))
],
),
SizedBox(
height: 2.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text('Size: '))),
Expanded(child: Text(size)),
],
),
SizedBox(
height: 2.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text('Last Modified Date: '))),
Expanded(child: Text(fileStat.modified.toString()))
],
),
SizedBox(
height: 2.0,
),
],
),
);
});
});
try the following
if (!mounted){
setState(() {
size = value;
}),
};

How to vertically expand container widget in flutter

trying to expand Expanded or Container vertically to match its height with Row widget height, here is my code
#override
Widget build(BuildContext context) {
return InkWell(
onTap: ()=> onDepartClicked(),
child: Container(
padding: EdgeInsets.all(16),
child: Card(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 8,
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(department.name,
overflow: TextOverflow.visible,
style: TextStyle(fontSize: 20),
),
Container(
margin: EdgeInsets.only(top: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image.asset("assets/images/feedback.png", width: 20, height: 20,),
SizedBox(width: 4,),
Text(department.phone),
SizedBox(width: 16,),
Image.asset("assets/images/feedback.png", width: 20, height: 20,),
SizedBox(width: 4,),
Text(department.type),
],
),
),
Container(margin: EdgeInsets.symmetric(vertical: 8),child: Divider(height: 0.3, color: Colors.grey,)),
Container(
child: Text(department.description,
maxLines: 3,
style: TextStyle(fontSize: 13),
),
)
],
),
),
),
Container(
width: 40,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(topRight: Radius.circular(4), bottomRight: Radius.circular(4))
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Image.asset("assets/images/feedback.png",
width: 20,
height: 20,
fit: BoxFit.scaleDown,
),
],
),
),
],
),
),
),
);
}
I want to expand this block in the above code (second child of the Row):
Container(
width: 40,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(topRight: Radius.circular(4), bottomRight: Radius.circular(4))
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Image.asset("assets/images/feedback.png",
width: 20,
height: 20,
fit: BoxFit.scaleDown,
),
],
),
),
I want to achieve this view with blue area expanded vertically in parent
Edit after more clarification on the question:
The idea behind the code below is like the This Image.
Left child of the row contains a column, the column has 3 children.
The first child of the column is the title, second one is a Row of phone and type and the last one is the description.
For "phone" and "type" you can use ListTile but you should put them on something like Flexible or define size for them.
I deinded a Listview and put 10 card inside it.
Here is the code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView.builder(
padding: EdgeInsets.all(16.0),
itemBuilder: (BuildContext context, int index) {
return _card();
},
shrinkWrap: true,
itemCount: 10,
),
),
);
}
Widget _card() {
return Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(
fit: FlexFit.tight,
flex: 5,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'UBIT',
overflow: TextOverflow.visible,
style: TextStyle(fontSize: 20),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Icon(Icons.message),
SizedBox(width: 4),
Text('+09210000000'),
SizedBox(width: 16),
Icon(Icons.message),
SizedBox(width: 4),
Text('Science'),
],
),
Divider(),
Text(
'Lorem Ipsum ist ein einfacher Demo-Text für ' +
'die Print- und Schriftindustrie. Lorem Ipsum ' +
'ist in der Industrie bereits der Standard Demo-Text' +
' seit 1500',
textAlign: TextAlign.justify,
),
],
),
),
Padding(
padding: EdgeInsets.only(left: 8.0),
child: Icon(
Icons.message,
size: 30.0,
),
),
],
),
),
);
}
}
Wrap the Container in a SizedBox with height:double.infinity to make it take all the available space, in your case the height of the row.
Expanded(
child: SizedBox(
height:double.infinity,
child:Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(topRight: Radius.circular(4), bottomRight: Radius.circular(4))
),
child: Image.asset("assets/images/feedback.png", width: 20, height: 20, fit: BoxFit.scaleDown,),
),
),
)

Improve overall layout on ListView of Rows

I'm trying to implement a ListView of Rows like this:
And this is my code:
import 'package:flutter/material.dart';
import 'package:good_driver_app/common/ExpandedButton.dart';
class ServicePetrolPage extends StatefulWidget {
// HomePage({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
_ServicePetrolPage createState() => _ServicePetrolPage();
}
class _ServicePetrolPage extends State<ServicePetrolPage> {
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('Petrol'),
),
body: Container(
child: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo",
),
),
Flexible(
child: new Text(
"Location",
),
),
Flexible(
child: new Text(
"Distance",
),
),
Flexible(
child: new Text(
"\$",
),
),
Flexible(
child: new Text(
"Facilities",
),
),
],
),
),
)
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 1",
),
),
Flexible(
child: new Text(
"Johnson Rd",
),
),
Flexible(
child: new Text(
"0.2 KM",
),
),
Flexible(
child: new Text(
"\$12.45",
),
),
Flexible(
child: new Text(
"ATM, Restaurant",
),
),
],
),
),
)
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 2",
),
),
Flexible(
child: new Text(
"Hennessy Rd",
),
),
Flexible(
child: new Text(
"0.5 KM",
),
),
Flexible(
child: new Text(
"\$12.88",
),
),
Flexible(
child: new Text(
"ATM",
),
),
],
),
),
)
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 3",
),
),
Flexible(
child: new Text(
"Lockhart Rd",
),
),
Flexible(
child: new Text(
"1.2 KM",
),
),
Flexible(
child: new Text(
"\$12.88",
),
),
Flexible(
child: new Text(
"Toilet",
),
),
],
),
),
)
],
),
),
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 4",
),
),
Flexible(
child: new Text(
"Canal Rd",
),
),
Flexible(
child: new Text(
"1.2 KM",
),
),
Flexible(
child: new Text(
"\$12.90",
),
),
Flexible(
child: new Text(
"Restaurant, Toilet",
),
),
],
),
),
)
],
),
),
],
),
),
);
}
}
And this is the result:
My questions are:
How to put horizontal gap between cells?
How to reduce the gap between rows?
This is how I'd do it.
ServicePetrolPage
class ServicePetrolPage extends StatefulWidget {
#override
_ServicePetrolPage createState() => _ServicePetrolPage();
}
class _ServicePetrolPage extends State<ServicePetrolPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Petrol'),
),
body: Container(
child: ListView(
children: <Widget>[
DataView(
distance: 'Distance',
facilities: ['Facilities'],
location: 'Location',
logo: ' Logo ',
price: '',
),
DataView(
logo: 'Logo 1',
location: 'Johnson Rd',
distance: '0.2 KM',
facilities: ['ATM', 'Restaurant'],
price: '12.45',
),
DataView(
logo: 'Logo 2',
location: 'Hennessy Rd',
distance: '0.5 KM',
facilities: ['ATM'],
price: '12.88',
),
DataView(
logo: 'Logo 3',
location: 'Lockhart Rd',
distance: '1.5 KM',
facilities: ['Toilet'],
price: '12.88',
),
DataView(
logo: 'Logo 4',
location: 'Canal Rd',
distance: '1.2 KM',
facilities: ['Restaurant', 'Toilet'],
price: '12.90',
),
],
),
),
);
}
}
DataView
class DataView extends StatelessWidget {
final String logo;
final String location;
final String distance;
final String price;
final List<String> facilities;
DataView({
this.location,
this.distance,
this.facilities,
this.logo,
this.price,
});
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text("$logo"),
Expanded(
flex: 2,
child: Center(child: Text("$location")),
),
Expanded(
flex: 1,
child: Center(child: Text("$distance")),
),
Expanded(
flex: 1,
child: Center(child: Text("\$$price")),
),
Expanded(
flex: 1,
child: Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
if (facilities != null)
...facilities.map((facility) {
return Padding(
padding: const EdgeInsets.all(0.0),
child: Text(
'$facility ',
overflow: TextOverflow.ellipsis,
),
);
}).toList(),
],
),
),
],
),
);
}
}
Since I am using List unwrapping syntax you will have to update your
SDK constraints in pubspec.yaml
pubspec.yaml
.
.
environment:
sdk: ">=2.2.2 <3.0.0"
1- Add a Container and set the height to 1 with a color you want (between each container row).
Container(
height: 1,
color: Colors.black,
),
2- Reduce the padding, I will change this padding: EdgeInsets.all(10) to this padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2)
Final code:
#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('Petrol'),
),
body: Container(
child: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo",
),
),
Flexible(
child: new Text(
"Location",
),
),
Flexible(
child: new Text(
"Distance",
),
),
Flexible(
child: new Text(
"\$",
),
),
Flexible(
child: new Text(
"Facilities",
),
),
],
),
),
)
],
),
),
Container(
height: 1,
color: Colors.black,
),
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 2),
height: 50.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 1",
),
),
Flexible(
child: new Text(
"Johnson Rd",
),
),
Flexible(
child: new Text(
"0.2 KM",
),
),
Flexible(
child: new Text(
"\$12.45",
),
),
Flexible(
child: new Text(
"ATM, Restaurant",
),
),
],
),
),
)
],
),
),
Container(
height: 1,
color: Colors.black,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 2",
),
),
Flexible(
child: new Text(
"Hennessy Rd",
),
),
Flexible(
child: new Text(
"0.5 KM",
),
),
Flexible(
child: new Text(
"\$12.88",
),
),
Flexible(
child: new Text(
"ATM",
),
),
],
),
),
)
],
),
),
Container(
height: 1,
color: Colors.black,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 3",
),
),
Flexible(
child: new Text(
"Lockhart Rd",
),
),
Flexible(
child: new Text(
"1.2 KM",
),
),
Flexible(
child: new Text(
"\$12.88",
),
),
Flexible(
child: new Text(
"Toilet",
),
),
],
),
),
)
],
),
),
Container(
height: 1,
color: Colors.black,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
child: Row(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(15.0),
height: 50.0,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: new Text(
"Logo 4",
),
),
Flexible(
child: new Text(
"Canal Rd",
),
),
Flexible(
child: new Text(
"1.2 KM",
),
),
Flexible(
child: new Text(
"\$12.90",
),
),
Flexible(
child: new Text(
"Restaurant, Toilet",
),
),
],
),
),
)
],
),
),
Container(
height: 1,
color: Colors.black,
),
],
),
),
);
}

How can I obtain this UI result?

I was trying to recreate a design concept from this guy(https://dribbble.com/shots/3812962-iPhone-X-Todo-Concept) but I'm getting some troubles with the ListView alignment or so I think.
What I'm trying to do is moving the List to the right without cutting the edges of the cards when I swipe.
I already tried with margin and padding but none of this applied to the container produces the results I want to obtain.Edges are cutted off when I swipe.
I leave here the Container with the ListView inside it.
Screenshoots of the actual app:
https://imgur.com/a/hJ96sEv
Container(
height: 350.0,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
itemCount: 3,
controller: scrollController,
scrollDirection: Axis.horizontal,
itemBuilder: (context, position) {
return GestureDetector(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Container(
width: 250.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(
cardsList[position].icon,
color: appColors[position],
),
Icon(
Icons.more_vert,
color: Colors.grey,
)
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0, vertical: 4.0),
child: Text(
"${cardsList[position].tasksRemaining} Tasks",
style:
TextStyle(color: Colors.grey),
),
),
Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 4.0),
child: Text(
"${cardsList[position].cardTitle}",
style:
TextStyle(fontSize: 28.0),
)),
Padding(
padding: const EdgeInsets.all(8.0),
child: LinearProgressIndicator(
value: cardsList[position]
.taskCompletion,
),
)
],
),
),
],
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
),
),
onHorizontalDragEnd: (details) {
animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 450));
curvedAnimation = CurvedAnimation(
parent: animationController,
curve: Curves.fastOutSlowIn);
animationController.addListener(() {
setState(() {
currentColor =
colorTween.evaluate(curvedAnimation);
});
});
if (details.velocity.pixelsPerSecond.dx > 0) {
if (cardIndex > 0) {
cardIndex--;
colorTween = ColorTween(
begin: currentColor,
end: appColors[cardIndex]);
}
} else {
if (cardIndex < 2) {
cardIndex++;
colorTween = ColorTween(
begin: currentColor,
end: appColors[cardIndex]);
}
}
setState(() {
scrollController.animateTo((cardIndex) * 256.0,
duration: Duration(milliseconds: 450),
curve: Curves.fastOutSlowIn);
});
colorTween.animate(curvedAnimation);
animationController.forward();
});
},
),
),
What I'm trying to do is moving the List to the right without cutting the edges of the cards when I swipe.
To achieve that goal you need a PageView instead of a ListView, that way you can swipe and "snap" the views when you reach and specific position:
PageView.builder(
itemCount: tasks.length,
controller: PageController(initialPage: 0, viewportFraction: 0.8),
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Color(0x40000000),
blurRadius: 10,
offset: Offset(0, 12),
),
],
),
child: Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10),
),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(15),
child: Column(
children: <Widget>[
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Icon(tasks[index].icon),
Expanded(
child: Container(
child: Align(
alignment: Alignment.topRight,
child: Icon(Icons.menu),
),
),
),
],
),
),
Expanded(
child: Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
"${tasks[index].tasks} tasks",
style: TextStyle(
color: Color(0xD0000000),
fontSize: 15,
),
),
SizedBox(height: 10),
Text(
"${tasks[index].title}",
style: TextStyle(
color: Color(0xD0000000),
fontSize: 24,
),
),
SizedBox(height: 10),
LinearProgressIndicator(
value: tasks[index].percentage,
backgroundColor: Color(0x300000FF),
)
],
),
),
),
],
),
),
),
),
);
},
)
The result of this implementation is something like this:
If you want to change the offset of the cards, you need to modify the value viewportFraction: 0.8 to anything you'd like. 1.0 is the value without offset.
You can find my full implementation over this Gist Github

Categories

Resources