Using this simple design, how can I display the second image under the listview? In reality the list will be fetched from firebase where each item is an ExpansionTile, so the height of the listview can in no way be fixed.
The column should be scrollable so you can see the full image if you scroll down below the list.
import 'package:flutter/material.dart';
List<Widget> list = <Widget>[
ListTile(
title: Text('CineArts at the Empire',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('85 W Portal Ave'),
leading: Icon(
Icons.theaters,
color: Colors.blue[500],
),
),
ListTile(
title: Text('The Castro Theater',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('429 Castro St'),
leading: Icon(
Icons.theaters,
color: Colors.blue[500],
),
),
];
class CartWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Column(children: <Widget>[
Image.network("https://via.placeholder.com/350x150"),
Expanded(
child: ListView(
children: list,
),
),
Image.network("https://via.placeholder.com/350x500"), // error: hides above widget
]));
}
}
The way I understood your problem is that you want the bottom image to appear inside the list view instead of under it, as if it was just another item. Solution: Make it just another item!
More concrete, this is how your implementation for a helper function that enriches the list with the image may look like:
List<Widget> _buildListWithFooterImage(List<Widget> items) {
return items.followedBy([
Image.network("https://via.placeholder.com/350x500")
]);
}
Then, you could use that function during your build:
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Image.network("https://via.placeholder.com/350x150"),
Expanded(
child: ListView(
children: _buildListWithFooterImage(list)
)
),
]
)
);
}
Also, I believe your question is similar to this one.
Related
I'm trying to create a listview widget with a floating action button on my Flutter app, but it's not working because Android Studio keeps on telling me that:
"the named parameter children isn't defined"
I basically can't put children in a body: Center widget, but I don't know why
I'm basically a beginner to Flutter and I'm still a bit confused about the basic syntax, and which widgets can hold which widgets, so any help is greatly appreciated! Thank you!
Here's my overall code that won't run due to the first error (in quotation marks above):
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: Home(),
));
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green[300],
title: Text(
'Welcome',
style: TextStyle(
fontSize: 25.0,
fontFamily: 'Raleway',
letterSpacing: 1.0,
),
),
centerTitle: true,
),
body: Center(
children: <Widget> [
ListView(
children: <Widget>[
Container(
height: 50,
color: Colors.green[100],
child: Text(
'Body Text',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 45.0,
letterSpacing: 1.0,
color: Colors.green[300],
),
),
),
Container(
height: 50,
color: Colors.green[100],
child: Text(
'Text'
),
),
],
),
FloatingActionButton(
onPressed: () {},
child: Text(
'+',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 35.0,
),
),
backgroundColor: Colors.green[300],
),
]
),
);
}
}
child parameter of Center Widget has a data type of Widget and so it can't take <Widget>[] as an input. It is similar to that an int won't accept String value. They are two different data types.
It seems that you want to have a list of data that is in center of the screen: For that you can use following code.
1.
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, // (optional) will center horizontally.
children: <Widget>[
.....
]
)
2.
Center(
child: ListView(
shrinkWrap:true;
children: <Widget>[
.....
]
)
)
It's simple. Because Center is a widget that does not take more than on widget as input.
It can only align one widget provided as a child.
For mulitple children you have to use some widget that takes a list of widgets as input.
Like:
Column
Row
ListView
Wrap
etc.
Center accepts only one widget check laytout page at https://flutter.dev/docs/development/ui/layout
Column(mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget> [
ListView(
children: <Widget>[
Container(
height: 50,
color: Colors.green[100],
child: Text(
'Body Text',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 45.0,
letterSpacing: 1.0,
color: Colors.green[300],
),
),
),
Container(
height: 50,
color: Colors.green[100],
child: Text(
'Text'
),
),
],
),
FloatingActionButton(
onPressed: () {},
child: Text(
'+',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 35.0,
),
),
backgroundColor: Colors.green[300],
),
]
),
);
Center is a widget that centres its child within itself.
So you can have only 1 child inside Center Widget.
You can take structure like,
Center(
child: Column(
children: <Widget>[
All Children you have
]
)
There are two types of widgets, one of which accepts a widget as a child and the other one accepts [Widget] as children.
Accepts a Widget as Child: Container widget, Center widget, Padding widget, , etc.
Accepts [Widget] as Children: Row widget, Column widget, Stack widget, Wrap widget, ListView widget, etc.
Center class :
A widget that centers its child within itself.
All layout widgets have either of the following:
A child property if they take a single child—
for example, Center or Container
A children property if they take a list of widgets—
for example, Row, Column, ListView, or Stack.
Add the Text widget to the Center widget:
const Center(
child: Text('Hello World'),
),
I'm trying to create a card with a text within a container but I would like to show only a part of the text and when the user click on "show more", show the rest. I saw a Widget to construct text like this here, but I need expand the card container either and I don't know how to do that because I need to know how many lines the text have to expand with the correctly size. Exists a way to calculate the size according the number of lines or characters?
I tried to create the card as follows, where the DescriptionText is the Widget on the link and specify a minHeight in the Container in the hope of expanding the container along with the text but did not work.
Widget _showAnswerCard(Answer answer, User user) {
return Card(
elevation: 3.0,
color: Theme.of(context).backgroundColor,
child: Container(
constraints: BoxConstraints(minHeight: 90),
padding: EdgeInsets.all(10.0),
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(flex: 1, child: _showUserAvatar(answer)),
Expanded(flex: 3, child: _showAnswerDetails(answer, user)),
],
),
));
}
Widget _showAnswerDetails(Answer answer, User user) {
return Flex(
direction: Axis.vertical,
children: <Widget>[
Expanded(
flex: 3,
child: DescriptionTextWidget(text: answer.content),
),
Expanded(
flex: 1,
child: _showAnswerOptions(),
)
],
);
}
I'll really appreciate if someone could help me with that.
Just use Wrap widget to wrap your Card widget.
Based on your link for suggested answer. I did change to use Wrap widget.
Jus do copy/paste below code and check.
import 'package:flutter/material.dart';
class ProductDetailPage extends StatelessWidget {
final String description =
"Flutter is Google’s mobile UI framework for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.";
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text("Demo App"),
),
body: new Container(
child: new DescriptionTextWidget(text: description),
),
);
}
}
class DescriptionTextWidget extends StatefulWidget {
final String text;
DescriptionTextWidget({#required this.text});
#override
_DescriptionTextWidgetState createState() =>
new _DescriptionTextWidgetState();
}
class _DescriptionTextWidgetState extends State<DescriptionTextWidget> {
bool flag = true;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Wrap(
children: <Widget>[
Card(
margin: EdgeInsets.all(8),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
child: Column(
children: <Widget>[
Container(
child: Text(
widget.text,
overflow: flag ? TextOverflow.ellipsis : null,
style: TextStyle(
fontSize: 15,
),
),
),
InkWell(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
flag ? "show more" : "show less",
style: new TextStyle(color: Colors.blue),
),
],
),
onTap: () {
setState(() {
flag = !flag;
});
},
),
],
)),
),
],
);
}
}
Result:
The solution I can think of is to use two labels, one for displaying only one line of text and one for displaying all the text. When the button is clicked, the two labels are alternately displayed in an animated manner. There is no computer at the moment, it is not convenient to verify, I hope to give you some help in the implementation of the program.
When I'm, not using the ListView.builder constructor in Flutter, the individual item is shown as expected from the JSON API:
when I use ListView.builder, nothing shows up. no Error!
I also tried a listview with Texts only that doesn't seem to work either.
Here's the code:
#override
Widget build(BuildContext context) {
return Container(
child: new Scaffold(
appBar: AppBar(
title: Text("the title"),//TODO edit this
backgroundColor: Colors.blueAccent),
body:
Column(
children: <Widget>[
FutureBuilder<List<dynamic>>(
future: getPosts2(),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListViewPosts(postsFrom: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),
],
),
),
);
}
}
And here is the ListViewPosts Stateless Widget:
class ListViewPosts extends
StatelessWidget {
final List<dynamic> postsFrom;
ListViewPosts({Key key,
this.postsFrom}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
FadeInImage.assetNetwork(
placeholder: 'assets/images/placeholder.png',
image: postsFrom[1]["featured_media"] == 0
? 'assets/images/placeholder.png'
: postsFrom[1]["_embedded"]["wp:featuredmedia"]
[0]["source_url"],
),
FadeInImage.assetNetwork(
placeholder: 'assets/images/placeholder.png',
image: postsFrom[2]["featured_media"] == 0
? 'assets/images/placeholder.png'
: postsFrom[2]["_embedded"]["wp:featuredmedia"]
[0]["source_url"],
),
new Row(
children: <Widget>[
Expanded(
child: Text(
"نووسهر: " +
postsFrom[1]["_embedded"]["author"][0]
["name"],
textAlign: TextAlign.right,
),
),
Expanded(
child: Text(
dateConvertor(
postsFrom[2]["date"].toString()),
textAlign: TextAlign.left,
),
),
],
),
ListView.builder(
itemCount: postsFrom.length, //== null ? 0 : postsFrom.length,
itemBuilder: (context, int index) {
Card(
child: Column(
children: <Widget>[
Text(postsFrom.toString()),
Container(
child: hawalImage(postsFrom, index),
),
new Padding(
padding: EdgeInsets.all(5.0),
child: new ListTile(
title: new Text("whatEver"),
subtitle: new Row(
children: <Widget>[
Expanded(
child: new Text(postsFrom[index]["title"]["rendered"]),
),
Expanded(
child: hawalDate(postsFrom, index),
),
],
),
),
),
new ButtonTheme.bar(
child: hawalBtnBar(),
),
],
),
);
},
),
You have to write return Card at the beginning of the curly brackets in the builder function. Also I would be cautious with using Expanded there, it might cause some errors.
Also you put a ListView inside a Column without defining it's height, so it will take up space indefinitely. Wrap it in a widget that provides height constraints(SizedBox, Expanded, ...)
Inside the Listview.builder() you could try to add the property shrinkWrap: true.
This worked for me. I was facing a similar issue.
Use with Expanded. Hopefully, it will solve your problem.
You have to write return Card at the beginning of the curly brackets in the builder function. Also I would be cautious with using Expanded there, it might cause some errors.
I'm new in Flutter+Dart and trying to increase font size but hard to understand documentation + implement to my work. Here is the file. How can I solve my problem?
import 'package:flutter/material.dart';
void main() => runApp(NewApp());
class NewApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('App Header'),
),
body: new Column(
children: [
new Container(
margin: new EdgeInsets.all(10.0),
child: new Card(
child: new Column(
children: <Widget>[
new Container(
padding: new EdgeInsets.all(10.0),
child: new Text('Hello Macaw'),
),
],
),
),
)
],
),
),
);
}
}
At the beginning this is hard to understand and implement. But once you understand, you will fall in love with the Flutter framework. Here is the solution:
new Text('Hello Macaw',style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),),
After that, format the code. That's it. Let me know if it works.
You can use style property of Text to change some of the property of the Text.
Example:
Text(
"Your text",
style: TextStyle(
fontSize: 20.0,
color: Colors.red,
fontWeight: FontWeight.w600,
),
)
It's a good practice to use predefined style for Text which gives you standard fontSize and fontWeight for the Text.
You can use them like this
style: Theme.of(context).textTheme.XYZ
XYZ can be body1, body2, title, subhead, headline etc.
While working on an application, we have an instance where we want a card to have an inkwell as well as a button on the card (also with an inkwell). However, I have been unable to determine a way to separate the gestures such that only the inkwell directly under the user's tap is invoked. As it is today, it appears that the tap 'bleeds through' to the next inkwell such that both splash effects are invoked. This is undesirable behavior, the application appears to be selecting the card not the invokable item on the card (note: actual application is much different but the same issue is present). I have reproduced this in a simple application to demonstrate the bleed through when the user pressed the button in the bottom right of the card. Is there something I am missing which can prevent this behavior? Thanks
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Card(
color: Colors.blue,
child: InkWell(
onTap: () { },
child: Container(
height: 150.0,
child: Align(
alignment: Alignment.bottomRight,
child: RaisedButton(
color: Colors.red,
onPressed: () { },
),
),
),
),
),
);
}
}
This is the normal expected InkWell behavior as most of the time you want to use it's tap feature for every widget in it's tree. So what you can do is to define a Stack and set the button in the z-axis absolute over the InkWell:
Widget build(BuildContext context) {
return new Scaffold(
body: Center(
child: Card(
color: Colors.blue,
child: Stack(
children: <Widget>[
InkWell(
onTap: () {
print("inkwell");
},
child: Container(
height: 150.0,
),
),
RaisedButton(
color: Colors.red,
onPressed: () {
print("button");
},
),
],
),
),
),
);
}
If you would want to set the button in the bottom right corner again you can set a Row and Colum around it and assign it's alignment:
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Center(
child: Container(
height: 150.0,
child: Card(
color: Colors.blue,
child: Stack(
children: <Widget>[
InkWell(
onTap: () {
print("inkwell");
},
child: Container(
height: 150.0,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
RaisedButton(
color: Colors.red,
onPressed: () {
print("button");
},
),
],
),
],
),
],
),
),
),
),
);
}
Upper code would result in seperated widgets: