class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
Storycard(),
],
),
),
);
}
}
class Storycard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, int index) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
child: Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
child: Column(
children: <Widget>[
ClipRRect(
child: Image.asset(
news[index].image,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0)),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(news[index].newsHeadline,
style: GoogleFonts.ubuntu(
fontSize: 17, fontWeight: FontWeight.bold)),
)
],
),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NewsDetails(news: news[index])));
});
},
itemCount: news.length,
);
}
}
I am trying here to have a list of scrollable cards. I want space above the cards to add some text. SO I tried using column and have a text and Listview Bulider as children. But the emulator is showing blank screen.
When the StoryCard() is alone used as the body the output comes with widgets. I can't add anything above the Listview. Can someone help.
enter image description here
Use Expanded class or Flexible class for the ListView.
ListView requires a finite height for it's content.
With your current code, ListView is having infinite height, hence the error. Expanded or Flexible helps you to have the remaining space to be utilized for your child
Solution
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
// here is the change
Expanded(
child: Storycard()
)
]
)
)
);
}
}
Using Flexible
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
// here is the change
Flexxible(
fit: FlexFit.loose,
child: Storycard()
)
]
)
)
);
}
}
Related
I'm trying to let my users increase the size of an image inside a fixed size Stack.
The chosen size can be way above the Stack's size.
This is the result I get for now, even though the image :
Here is the relevant code :
Expanded(
child: AspectRatio(
aspectRatio: myCustomScreen.width / myCustomScreen.height,
child: ClipRRect(
borderRadius: BorderRadius.circular(14),
child: LayoutBuilder(
builder: (context, boxConstraint) {
return Stack(
alignment: Alignment.center,
fit: StackFit.passthrough,
children: [
Container(
color: Colors.blue,
),
//This object doesn't overflow when its width is above the
UnconstrainedBox(
child: Image(
width: (object.width.toDouble() * boxConstraint.biggest.width) / myCustomScreen.width,
image: NetworkImage("www.images.com/image.png", scale: 1)),
),
],
);
},
),
),
),
),
How can I let my users view the real size of the image inside this view without being constrained by the stack ?
Thank you !
Stack has a property called clipBehavior you can use it like this to enable overflow:
Stack(
clipBehavior: Clip.none,
// Your code continues here
Edit: Testing your code I made ti work on dart pad. The steps were, remove the UnconstrainedBox and used the image scale to resize it alongside with the fit property defined as none:
here's the code that I used on darted: https://dartpad.dartlang.org/
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
Expanded(
child: AspectRatio(
aspectRatio: 200 / 400,
child: ClipRRect(
borderRadius: BorderRadius.circular(14),
child: LayoutBuilder(
builder: (context, boxConstraint) {
return Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
fit: StackFit.passthrough,
children: [
Container(
color: Colors.blue,
),
Image(
fit: BoxFit.none,
image: NetworkImage(
"https://images.pexels.com/photos/13406218/pexels-photo-13406218.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
scale: 1 / (_counter + 1),
),
),
],
);
},
),
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
This problem only happens inside Drawer
I wanted to shape the ripple effect of my ExpansionTile so I used the Material widget and it works, but when the tile expands, the background color of the tiles below ExpansionTile does not move with them.
When ExpansionTile is collapsed
When ExpansionTile is expanded
I found out that when I remove SingleChildScrollView the problem solves but I need items to scroll. Also when ScrollPhysics has been set to AlwaysScroll, scrolling till the end of the scroll's possible position would rerender items and fix the issue.
Reproducible Example:
void main() {
runApp(
MaterialApp(
title: 'Title',
home: Scaffold(
appBar: AppBar(
title: const Text('Title'),
),
drawer: const MyList(),
body: Container(),
),
),
);
}
class MyList extends StatelessWidget {
const MyList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
items(),
],
),
),
);
}
Widget items() {
return Wrap(
runSpacing: 12,
children: [
menu(),
const ListTile(title: Text('title'), tileColor: Colors.grey),
const ListTile(title: Text('title')),
]
);
}
Widget menu() {
return Material(
clipBehavior: Clip.antiAlias,
type: MaterialType.transparency,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)
),
child: const ExpansionTile(
leading: Icon(Icons.group),
title: Text('title'),
children: [
ListTile(title: Text('title')),
ListTile(title: Text('title')),
],
),
);
}
}
If you want to avoid SingleChildScrollView and still be able to scroll over a list, you can use ListView.builder link: - ListView.builder flutter.dev
Try removing type: MaterialType.transparency,
class MyList extends StatelessWidget {
const MyList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
child: Column(
children: [
for (int i = 0; i < 2; i++) items(),
],
),
),
);
}
Widget items() {
return Wrap(
children: [
menu(),
const ListTile(
title: Text('title'),
tileColor: Colors.grey,
),
const ListTile(title: Text('title')),
],
);
}
Widget menu() {
return Material(
clipBehavior: Clip.antiAlias,
// type: MaterialType.transparency,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
child: const ExpansionTile(
leading: Icon(Icons.group),
title: Text('title'),
children: [
ListTile(title: Text('title')),
ListTile(title: Text('title')),
],
),
);
}
}
I asked for this problem on flutter's Github repo and I got the answer.
Just need to use ListTileTheme widget instead of Material widget.
Github issue link:
https://github.com/flutter/flutter/issues/112372
I want to achieve the following PhonePe UI in flutter. How can I make sure that the "Proceed" button always remains at the bottom position ?
Image
You can copy paste run full code below
You can use bottomSheet attribute of Scaffold
return Scaffold(
...
bottomSheet: Container(
width: MediaQuery.of(context).size.width,
child: RaisedButton(
child: Text('PROCEED'),
onPressed: () {},
),
),
);
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BottomSheetTestPage(),
);
}
}
class BottomSheetTestPage extends StatefulWidget {
#override
_BottomSheetPageState createState() => _BottomSheetPageState();
}
class _BottomSheetPageState extends State<BottomSheetTestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('bottom sheet'),
),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(index.toString()),
subtitle: Text("${index}"),
);
},
itemCount: 300,
),
bottomSheet: Container(
width: MediaQuery.of(context).size.width,
child: RaisedButton(
child: Text('PROCEED'),
onPressed: () {},
),
),
);
}
}
You will solve using Expanded widget.
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: MaterialButton(
onPressed: () => {},
child: Text(’Proceed'),
),
),
),
You can expand the first part of the layout
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Text('FirstPart')),
InkWell(
onTap: () => print('pushed'),
child: Container(
width: 100,
height: 60,
alignment: Alignment.center,
color: Colors.black26,
child: Text('PROCEED'),
),
)
],
);
}
}
You can use stack like this
Stack(
children: <Widget>[
//your other widgets here
Align(
alignment: Alignment.bottomCenter,
child: yourButton,
)
],
),
a simple way to do this is using a Scaffold since the scaffold has a bottomNavigationBar attribute that takes a widget then you can simply pass to it a button like this
Widget build(BuildContext context) {
return Scaffold(
// will always be at the bottom
bottomNavigationBar: FlatButton(onPressed: (){},child: Text("Proceed"),),
body: Text("your body goes here"),
);
}
I am a new flutter developer.I try to make listview to view a set of data that comes from the database.The list now works, but as follows:
Now it is not presented separately.I need to display every element in the card.An example of what I'm trying to do:
In this picture, each item on the card is separate and separated from the second.How I can do it?If anyone knows the solution please help me.
my code now like that:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: Card(
child :FutureBuilder<List<Flowerdata>>(
future: fetchFlowers(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Center(
child: CircularProgressIndicator()
);
return ListView(
children: snapshot.data
.map((data) => Column(children: <Widget>[
GestureDetector(
onTap: ()=>{
getItemAndNavigate(data.id, context)
},
child: Row(
children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child:
Image.network(data.flowerImageURL,
width: 200, height: 100, fit: BoxFit.cover,))),
Flexible(child:
Text(data.flowerName,
style: TextStyle(fontSize: 18))
),
]),),
Divider(color: Colors.black),
],
))
.toList(),
);
},
)
),
),
]
)
);
}
You need to wrap your item's Column(not the FutureBuilder) in with Card
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[
Expanded(
child: FutureBuilder<List<Flowerdata>>(
future: fetchFlowers(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
return ListView(
children: snapshot.data
.map((data) => Card(
child: Column(
children: <Widget>[
GestureDetector(
onTap: () => {getItemAndNavigate(data.id, context)},
child: Row(children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.network(
data.flowerImageURL,
width: 200,
height: 100,
fit: BoxFit.cover,
))),
Flexible(
child: Text(data.flowerName,
style: TextStyle(fontSize: 18))),
]),
),
Divider(color: Colors.black),
],
),
))
.toList(),
);
},
),
),
]));
}
Setup
Start a new Flutter project. I'm calling mine flutter_listview.
Open main.dart and replace the code with the following:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ListViews',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: Scaffold(
appBar: AppBar(title: Text('ListViews')),
body: BodyLayout(),
),
);
}
}
class BodyLayout extends StatelessWidget {
#override
Widget build(BuildContext context) {
return _myListView(context);
}
}
// replace this function with the code in the examples
Widget _myListView(BuildContext context) {
return ListView();
}
Note the _myListView() function at the end. You will be replacing this with the code in the examples below
Basic types of ListViews
Static ListView
If you have a short list of items that don't change, then you can use the default ListView constructor to make it. This is useful for making something like a settings menu page.
Replace _myListView() with the following:
Widget _myListView(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
);
}
Run the app and you should see the following image. (After this when refreshing, usually hot reload works fine, but I find at times I need to do a hot restart or even completely stop and restart the app.)
ListTile customization
The Flutter team designed the ListTile widget to handle the normal content that you would want in a list. This means that most of the time there is no need to define a custom layout. You can just use the default ListTile for each item in the list. When we made a ListView in the example above we only used the title option. But we can also show subtitles, images, and icons.
Replace _myListView() with the following
Widget _myListView(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.wb_sunny),
title: Text('Sun'),
),
ListTile(
leading: Icon(Icons.brightness_3),
title: Text('Moon'),
),
ListTile(
leading: Icon(Icons.star),
title: Text('Star'),
),
],
);
}
The leading is for adding an icon or image at the start of the ListTile.
You can also add an icon at the end if you specify the trailing attribute.
ListTile(
leading: Icon(Icons.wb_sunny),
title: Text('Sun'),
trailing: Icon(Icons.keyboard_arrow_right),
)
The right arrow icon makes it look like the list items are clickable, but they aren't. Not yet. We will see how to add touch events in the next section. It's easy. (Hint: onTap )
Instead of icons, we can also use images. The recommended image option is to use a CircleAvatar widget.
Replace _myListView() with the following:
Widget _myListView(BuildContext context) {
return ListView(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('assets/sun.jpg'),
),
title: Text('Sun'),
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('assets/moon.jpg'),
),
title: Text('Moon'),
),
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('assets/stars.jpg'),
),
title: Text('Star'),
),
],
);
}
If you want MASTERING FLUTTER LISTVIEWS enter link description here
I am quite new to flutter and I've been trying to set up a profile page for my app but it seems like I don't quite understand how these flutter widgets come together, I apologize if my question is quite dumb but I've been googling and failing at getting this to work. So basically I have a scaffold which holds a container thats supposed to display profile info (email, name, etc.), under it I'd like to place a listview, but flutter has been boggling my mind, I can't seem to understand how layouts work together, here is my code. When I try to do buildPage(), I get an error that the scaffold has infinite size, using buildBox() alone works. I'm not sure how to go about this. Any Help is appreciated
import 'package:flutter/material.dart';
class ProfileBox extends StatefulWidget {
final String userEmail;
const ProfileBox(this.userEmail);
#override
_ProfileBoxState createState() => _ProfileBoxState();
}
class _ProfileBoxState extends State<ProfileBox> {
#override
Widget build(BuildContext context) {
return _buildPage();
}
Widget _buildBox(){
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Container(
margin: const EdgeInsets.only(top: 20.0),
decoration: BoxDecoration(
color: Color(0xFF8185E2), border: Border.all(
color: Color(0xFF8185E2),
),
borderRadius: BorderRadius.all(Radius.circular(20))
),
height: constraints.maxHeight / 2.5,
width: MediaQuery.of(context).size.width - (MediaQuery.of(context).size.width * 5)/100,
child: Center(
child: Text(
widget.userEmail,
textAlign: TextAlign.center,
),
),
);
},
),
),
);
}
Widget _buildPage()
{
return Column(children: <Widget>[
_buildBox(),
_buildList(),
],);
}
Widget _buildList()
{
return ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
);
}
}
I just modified your code with Scaffold put the top Widget before the SafeArea, Please check the below code of it.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return _buildPage();
}
Widget _buildPage() {
return SafeArea(
top: true,
child: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.only(top: 20.0),
decoration: BoxDecoration(
color: Color(0xFF8185E2),
border: Border.all(
color: Color(0xFF8185E2),
),
borderRadius: BorderRadius.all(Radius.circular(20))),
height: MediaQuery.of(context).size.height / 2.5,
width: MediaQuery.of(context).size.width -
(MediaQuery.of(context).size.width * 5) / 100,
child: Center(
child: Text(
"YOUR_EMAIL",
textAlign: TextAlign.center,
),
),
),
Expanded(
child: _buildList(),
)
],
),
),
);
Column(
children: <Widget>[
// _buildBox(),
_buildList(),
],
);
}
Widget _buildList() {
return ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
);
}
}
And output of the program as follow
Scaffold Widget should be a top Widget that contains the Column widget and all children Widget. I think you can start learning how to layout Widget in Flutter in order to understand more the way how Widget works, and the good place can be: https://flutter.dev/docs/development/ui/layout#lay-out-a-widget
Coming back to your question, you can just fix a bit to make it work:
class _ProfileBoxState extends State<ProfileBox> {
#override
Widget build(BuildContext context) {
return _buildPage();
}
Widget _buildBox() {
return Align(
alignment: Alignment.topCenter,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Container(
margin: const EdgeInsets.only(top: 20.0),
decoration: BoxDecoration(
color: Color(0xFF8185E2),
border: Border.all(
color: Color(0xFF8185E2),
),
borderRadius: BorderRadius.all(Radius.circular(20))),
height: constraints.maxHeight / 2.5,
width: MediaQuery.of(context).size.width -
(MediaQuery.of(context).size.width * 5) / 100,
child: Center(
child: Text(
widget.userEmail,
textAlign: TextAlign.center,
),
),
);
},
),
);
}
Widget _buildPage() {
return Scaffold(
body: Column(
children: <Widget>[
_buildBox(),
_buildList(),
],
),
);
}
Widget _buildList() {
return ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
);
}
}