I have been researching Flutter and a question arose --
I have an array with some information, and I need to add cards based on this array.
Currently, I create a loop and add the cards which follow the structure of my array and my program listed below. Note that when I call statement passing the parameters, the code runs without any problem, but the following code does not work for me:
import "package:acessorias/pages/global.variables.dart";
import "package:flutter/material.dart";
class Comunicados extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Center(
child: SizedBox(
width: 150,
child: Image.asset("assets/image/logo.png"),
),
),
actions: <Widget>[
Container(
width: 60,
child: FlatButton(
child: Icon(
Icons.search,
color: Color(0xFFBABABA),
),
onPressed: () => {},
),
),
],
),
body: Container(
color: Color(0xFFF2F3F6),
child: ListView(
children: <Widget>[
comunicado(comunicados[0]["LogNome"], comunicados[0]["EmComDTH"],
comunicados[0]["EmComDesc"]),
comunicado(comunicados[1]["LogNome"], comunicados[1]["EmComDTH"],
comunicados[1]["EmComDesc"]),
comunicado(comunicados[2]["LogNome"], comunicados[2]["EmComDTH"],
comunicados[2]["EmComDesc"]),
comunicado(comunicados[3]["LogNome"], comunicados[3]["EmComDTH"],
comunicados[3]["EmComDesc"]),
comunicado(comunicados[4]["LogNome"], comunicados[4]["EmComDTH"],
comunicados[4]["EmComDesc"]),
comunicado(comunicados[5]["LogNome"], comunicados[5]["EmComDTH"],
comunicados[5]["EmComDesc"])
],
),
),
);
}
}
Widget comunicado(user, data, msg) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage("assets/image/foto.png"),
),
title: new Text(user),
subtitle: Text(data),
trailing: Icon(Icons.more_vert),
),
/*Container(
child: Image.asset("assets/image/post.png"),
),*/
Container(
padding: EdgeInsets.all(10),
child: Text(msg),
),
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: Icon(Icons.favorite),
onPressed: () {},
),
FlatButton(
child: Icon(Icons.share),
onPressed: () {},
),
],
),
),
],
),
);
}
Solution
body: ListView.builder(
itemCount: comunicados.length,
itemBuilder: (context, index) {
/*return ListTile(
title: Text('${comunicados[index]}'),
);*/
return comunicado(comunicados[index]['LogNome'],
comunicados[index]["EmComDTH"], comunicados[index]["EmComDesc"]);
},
),
You can use data model in another dart file like Comunicado.dart
class Comunicado{
String user;
String data;
String msg;
Comunicado(
{this.user, this.data, this.msg});
}
after that you can make list of data model with the static data or etc like
List getComunicado(){
return[
Comunicado(
user: comunicados[0]["LogNome"],
data: comunicados[0]["EmComDTH"],
msg: comunicados[0]["EmComDesc"],
),
Comunicado(
user: comunicados[1]["LogNome"],
data: comunicados[1]["EmComDTH"],
msg: comunicados[1]["EmComDesc"],
),
]
}
in my case, i put it into initial state and don't forget to declare comm
#override
void initState() {
super.initState();
comm= getComunicado();
}
for custom card
Card makeCard(Comunicado newComm) => Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage("assets/image/foto.png"),
),
title: new Text("${newComm.user}"),
subtitle: Text("${newComm.data}"),
trailing: Icon(Icons.more_vert),
),
/*Container(
child: Image.asset("assets/image/post.png"),
),*/
Container(
padding: EdgeInsets.all(10),
child: Text("${newComm.msg}"),
),
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: Icon(Icons.favorite),
onPressed: () {},
),
FlatButton(
child: Icon(Icons.share),
onPressed: () {},
),
],
),
),
],
),
);
and for last you can call make card on listview
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: comm.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(comm[index]);
},
),
Related
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 1,
backgroundColor: appBarColor,
centerTitle: true,
title: const Text('News'),
),
body: Column(
children: [
news.length < 2
? ImageSlideshow(
children: [NewsSlideWidget0(news: news)],
)
: ImageSlideshow(
children: [
NewsSlideWidget0(news: news),
NewsSlideWidget1(news: news)
],
),
Container(
color: Colors.white,
child: ListTile(
// selectedTileColor: Colors.white,
title: Text(news_screen_title, style: news_screen_title_tstyle),
subtitle: Text(news_screen_subtitle),
),
),
news.isEmpty
? const CircularProgressIndicator()
: Expanded(
child: LazyLoadScrollView(
onEndOfPage: () => loadNextPage(),
scrollOffset: 10,
child: ListView.builder(
itemCount: news.length,
itemBuilder: (BuildContext context, int i) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewsInnerScreen(
title: news[i].title,
date: news[i].date,
image: news[i].images[0],
content: parse(news[i].content).body!.text,
),
),
);
},
child: Container(
child: ListTile(
contentPadding: EdgeInsets.all(15),
title: Text(
news[i].title,
),
subtitle: Column(
children: [
Text(
parse(news[i].content).body!.text,
style:
),
Text(
news[i].date,
),
],
),
trailing: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
minHeight: 300,
maxWidth: 104,
maxHeight: 300,
),
child: ClipRRect(
child: Image(
image: NetworkImage(
news[i].images[0],
),
),
),
),
),
),
),
);
},
),
),
),
],
),
);
}
my screen is like this I want this column to scrollable I tried singlechildscrollview and listview those did not work for me and I use a plugin for pagination and I use more widgets also and I extracted that and u I use image slide show packages for carousel so how can I do that I am new to flutter please let me know
All list builder in Flutter have property called "shrinkWrap"
Just turn it to "true"
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?
I'm trying to create scrollable list of posts, but instead i got static non-scrollable bloc of strings, which is overflowing.
Example:
Oveflowing:
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
child: Container(
child: Column(children: [
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
);
},
),
]))));
}
Moreover, they all go like a single card, without separating.
Edited code, which is scrolling but doesn't separate posts
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
height: 500,
child:
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return Card(child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
) );
},
),
));
}
I'm tried to find error with documentation, but...
Column and Listview take the maximum available height. therefore, the height of Listview which here is a child of Column should be constrained. You can do so by wrapping your ListView inside Expanded:
child: Column(
children: [
Expanded(
child: ListView(
Also, if your list is long, it is not recommended to set shrinkwrap to true. Because it makes the ListView to load all its items when the layout gets built. So it can slow down performance.
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
height: MediaQuery.of(context).height*0.8, // add this line
child:
// Container( // do not need this
// child: // and this do not need
// Column(children: [ // and this do not need
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
ListView( // change this to ListView.builder for more performance
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
);## Heading ##
},
),
// ]) // comment this
// ). // and comment this
)
);
}
I'm trying to make posts like on Twitter, where every post is a single separated item, but they all go like big single card, without separating. I'm kinda new with Flutter and bad at explanations, but I hope u got it.
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
height: 500,
child:
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return Card(child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
) );
},
),
));
}
Example of how it looks:
I'm tried to find error with documentation, but...
Write if u need some more code or explanations.
Please help me if you can <3
You need to add each of the mapped item of your data with Card instead of your parent ListView. Something like this:
return ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child:
// Use card here.
Card(child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
),
)
],
);
You can try ListView.separated
Try:
List.generate(lentgh, (index) {
return Text("$index"); // custom widget
}),
Is there any way to change the text labels of the Continue and Cancel Buttons of the stepper in flutter? Stepper seems to be the perfect choice for what I want to do (long form with several "stages") and before I go try to build one from scratch just to get other labels for the buttons I thought I may ask..
Anybody knows if/how thats possible?
Yes, you can by providing a controlsBuilder callback. Which has to be a function that takes two other functions (onStepContinue and onStepCancel) which are the actions that you will have to pass to the new buttons you'll create in order for them to act as they should.
Then you can declare anything you want (in this case a row with two buttons) as long you pass the two functions (onStepContinue and onStepCancel) for them to work as its expected:
Stepper(
controlsBuilder: (BuildContext context,
{VoidCallback? onStepContinue, VoidCallback? onStepCancel}) {
return Row(
children: <Widget>[
TextButton(
onPressed: onStepContinue,
child: const Text('NEXT'),
),
TextButton(
onPressed: onStepCancel,
child: const Text('EXIT'),
),
],
);
},
steps: const <Step>[
Step(
title: Text('A'),
content: SizedBox(
width: 100.0,
height: 100.0,
),
),
Step(
title: Text('B'),
content: SizedBox(
width: 100.0,
height: 100.0,
),
),
],
);
flutter version 2.8.1
inside the Stepper you can use controlsBuilder
you can change buttons
controlsBuilder: (context,_) {
return Row(
children: <Widget>[
TextButton(
onPressed: (){},
child: const Text('NEXT'),
),
TextButton(
onPressed: (){},
child: const Text('EXIT'),
),
],
);
},
controlsBuilder: (BuildContext context, ControlsDetails details) {
final _isLastStep = _currentStep == _getSteps.length - 1;
return Container(
margin: const EdgeInsets.only(top: 50),
child: Row(children: [
Expanded(
child: ElevatedButton(
child: Text(_isLastStep ? 'Send' : 'Next'),
onPressed: details.onStepContinue)),
const SizedBox(
width: 12,
),
if (_currentStep != 0)
Expanded(
child: ElevatedButton(
child: Text('Back'),
onPressed: details.onStepCancel))
]));
},
I m late for the discussion.
But i have just done it and think it is good to share.
The code is able to control the Text for each step as the code below.
Each step will have difference text, manage to do for 3 steps. If more than that, the code will be quite messy.
Hope it helps someone who is looking for it.
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
children: <Widget>[
_activeCurrentStep == 0
? TextButton(
onPressed: onStepContinue,
child: const Text('NEXT'),
)
: _activeCurrentStep == 1
? Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextButton(
onPressed: onStepContinue,
child: const Text('NEXT'),
),
TextButton(
onPressed: onStepCancel,
child: const Text('BACK'),
),
],
),
)
: _activeCurrentStep >= 2
? Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
TextButton(
onPressed: onStepContinue,
child: const Text('SAVE'),
),
TextButton(
onPressed: onStepCancel,
child: const Text('BACK'),
),
],
),
)
: TextButton(
onPressed: onStepCancel,
child: const Text('BACK'),
),
],
);
},
Solution for flutter version > 2.8.1
In flutter version > 2.8.1 you can not use this for change the labels or buttons:
controlsBuilder: (context, {onStepContinue, onStepCancel}) {...}
Use this:
controlsBuilder: (context, _) {...}
Or this:
controlsBuilder: (context, onStepContinue) {...}
controlsBuilder: (context, onStepCancel) {...}
This is a complete example changing the labels text and colors:
Stepper(
controlsBuilder: (context, _) {
return Row(
children: <Widget>[
TextButton(
onPressed: () {},
child: const Text(
'NEXT',
style:
TextStyle(color: Colors.blue),
),
),
TextButton(
onPressed: () {},
child: const Text(
'EXIT',
style:
TextStyle(color: Colors.blue),
),
),
],
);
},
//Rest of the Stepper code (currentStep, onStepCancel, onStepContinue, steps...)
//...
)