I inserted 6 cards, however it is not possible to scroll the screen.
According to the image below, a red stripe appears in the footer, and the screen does not scroll.
What is missing to be able to scroll the screen?
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: "Myapp",
home: new HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) => new Scaffold(
appBar: new AppBar(
backgroundColor: new Color(0xFF26C6DA),
),
body: new Column(
children: <Widget>[
new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text('The Enchanted Nightingale'),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
],
),
),
...
...
...
],
)
);
}
Columns don't scroll. Try replacing your outer Column with a ListView. You may need to put shrinkWrap: true on it.
To make a column scrollable, simply wrap it in a SingleChildScrollView.
This might do the trick, worked like charm for me:
shrinkWrap: true, physics: ClampingScrollPhysics(),
I needed placing SingleChildScrollView inside Column. The SingleChildScrollView also needed Column as a child, but the scroll wasn't working for me in that case. The solution was to wrap the SingleChildScrollView with Expanded. So here's how it looked:
Column(
children: <Widget>[
MyFirstWidget(),
Expanded(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// Scrollable content.
],
),
),
),
],
),
you have to put it on ListView.builder
ListView.builder(
itemBuilder: (BuildContext context, int index){
final item = yourItemLists[index];
new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text('The Enchanted Nightingale'),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
],
),
);
},
itemCount: yourItemLists.length,
);
A column in a column make the layout impossible to calculate without setting height.
The second column is useless since it contains only one element, try to put the ListTile directly as the body of the Card.
You should use ListView.builder in place of the inner column (as I suggested above that columns are not scrollable).
Set shrinkWrap: true, and physics: ClampingScrollPhysics() inside ListView.builder. Just using shrinkWrap: true didn't solve my problem. But setting physics to ClampingScrollPhysics() started to make it scroll.
There are generally two ways to make a screen scrollable. One is by using Column, and the other is by using ListView.
Use Column (wrapped in SingleChildScrollView):
SingleChildScrollView( // Don't forget this.
child: Column(
children: [
Text('First'),
//... other children
Text('Last'),
],
),
)
Use ListView:
ListView(
children: [
Text('First'),
//... other children
Text('Last'),
],
)
This approach is simpler to use, but you lose features like crossAxisAlignment. For this case, you can wrap your children widget inside Align and set alignment property.
You can also Wrap the parent Column in a Container and then wrap the Container with the SingleChildscrollView widget. (This solved my issue).
Just Add physics: ClampingScrollPhysics(),
Related
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.
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.
In my MaterialApp I have a Column inside a horizontal ListView.
Inside that Column is a Text widget.
ListView(
children: [
Column(
children: [
Text('this is the text widget'),
// here I have another widget placed, just imagine a rectangle
],
],)
textAlign: TextAlign.center, nor surrounding it with a Center will change the position of the Text. The Text will always stay in the top left corner.
Also, I saw a lot about axis alignments in answers regarding similar problems, but I tried every axis settings I saw without success.
As you can see the text in the upper image is not centered.
You need crossAxisAlignment: CrossAxisAlignment.center
ListView(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('this is the text widget'),
// here I have another widget placed, just imagine a rectangle
],
),
],
)
EDIT:
Since, you are unsatisfied with above answer. I re-did what you exactly want. Please refer below code:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'MediaQuery Demo',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
Widget widgetToRepeat() {
return new Column(
children: <Widget>[
new Text('Hello'),
new Container(
width: 100.0,
height: 150.0,
color: Colors.green,
margin: new EdgeInsets.all(8.0),
)
],
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Demo'),
),
body: new Column(
children: <Widget>[
new Container(
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
widgetToRepeat(),
widgetToRepeat(),
widgetToRepeat(),
widgetToRepeat(),
widgetToRepeat(),
],
),
height: 150.0 + 16.0 + 20.0 + 16.0,
padding: new EdgeInsets.all(10.0),
)
],
),
);
}
}
I hope this helps. I am able to achieve text at horizontally center.
return new ListView(children: [
new Center(
child: Column(
children: [
Text('this is the text widget'),
// here I have another widget placed, just imagine a rectangle
],
),
)
]);
warp with new Center Widget
I am doing a Flutter app and managed to show the AdMob banner ad, however the ad overlaps the bottom of my app's main screen:
By following this article, I managed to make the app screen's bottom properly displayed, but the persistentFooterButtons is sacrificed, which I think is not an ideal solution.
I am thinking about putting the Scaffold object and a fixed height area into a column that is contained by a Center object, something similar to the following:
#override
Widget build(BuildContext context) {
return new Center(
child: new Column (
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Expanded (
child: _getScaffold(),
),
new Expanded (
child: new Container(height: 50.0,)
)
],
),
);
}
But in this way I get the exception "A RenderFlex overflowed by 228 pixels on the bottom":
Anybody can show me how to build such layout? I want every component of my scaffold properly displayed, with a fixed height dummy footer that is ok to be overlapped by the Admob's banner ad.
Any help is much welcome.
Jimmy
Also we can add some trick like bottomNavigationBar under the Scaffold
bottomNavigationBar: Container(
height: 50.0,
color: Colors.white,
),
This will take floating button up.
Finally I got it:
#override
Widget build(BuildContext context) {
return new Center(
child: new Column (
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Expanded (
child: _getScaffold(),
),
new Container(height: 50.0,
child: new Placeholder(color:Colors.blue))
],
),
);
}
The trick is Expanded here is for the Scaffold only, but for the dummy footer just a fixed height Container is required. Now I can display everything available from the Scaffold object.
Layout building of Flutter sometimes really confuses me...
If I understand your question well, I think you want to have your ad shown from the bottom while using a FAB. I think using a Stack widget here is a good solution, I created this example in a rush but should be enough to show you what I mean:
class AdBar extends StatefulWidget {
#override
_AdBarState createState() => new _AdBarState();
}
class _AdBarState extends State<AdBar> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: new ListView(
children: new List.generate(50, (int index) {
return new Text("widgets$index");
}),
),
persistentFooterButtons:
<Widget>[
new Stack(
children: <Widget>[
new Container (
color: Colors.transparent,
child: new Material(
color: Colors.cyanAccent,
child: new InkWell(
onTap: () {
},
child: new Container(
//color: Colors.cyanAccent,
width: MediaQuery
.of(context)
.size
.width * 0.90,
height: MediaQuery
.of(context)
.size
.height * 0.25,
),
),),),
new Positioned(
right: 0.0,
child: new FloatingActionButton(
onPressed: () {}, child: new Icon(Icons.fastfood)))
],
)
]
);
}
}