Expanded column with scrolling, floating button and fixed rows - flutter

I've been trying to achieve this layout with flutter for many hours, but with no luck
this is what i have so far and it doesn't work
*Important: The fixed rows will have a dynamic height.
Scaffold(
body: Column(
children: [
Container(
child: Text('First row'),
),
Expanded(
child: ListView(shrinkWrap: true, children: [
Stack(
children: [
Container(
child: Column(
children: [
Text(),
Container(),
],
),
),
Positioned(
bottom: 0,
child: Container(
child: Text('Button'),
),
),
],
),
]),
),
Container(
child: Center(child: Text('Footer')
),
)
],
),
),
I do not have much more to say. I don't know how many variants I have tried ... any idea is welcome thanks

In flutter we have app bar and navigation bar, which will not scroll by default and inside you can use columns and rows achieve this type.
Scaffold(
appBar: AppBar(), // top bar
bottomNavigationBar: Container(), // bottom bar which doesn't scroll at least by default
body: SingleChildScrollView(child: Column()),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
));

Flutter has a built-in stationary floating button, called a FloatingActionButton. That should take care of your button needs.
As for the central scrolling section, a ListView inside an Expanded should do the trick. You shouldn't need shrinkWrap when you're inside an Expanded widget, since constraints will be provided to ListView from Expanded during the layout phase of non-fixed size widgets (such as ListView).
Here's a copy/past example:
import 'package:flutter/material.dart';
class FabColRowPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FAB Row Column'),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => print('FAB was pressed'),
),
body: Column(
children: [
TopRow(),
Expanded(child: ScrollingBody()),
BottomRow(),
],
),
);
}
}
class TopRow extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text('TOP ROW'),
);
}
}
class BottomRow extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text('BOTTOM ROW'),
);
}
}
class ScrollingBody extends StatelessWidget {
final List<String> items = List.generate(20, (index) => 'Item #$index');
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
);
}
}

why not you used floatingAction button in Scaffold
eg: Scaffold(
floatinActionButton:FloatinActionButton(
child:Icon(Icons.add),),
body: Column(
children: [
Container(
child: Text('First row'),
),

Use FloatingActionButton:
Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Container(
padding: EdgeInsets.only(bottom: 100),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
print('press...');
},
),
),

body: Column(
children: [
Row(........),
Expanded(child: ListView(children: [....])),
Row(........),
]
)
your Scaffold body needs to be like this.

Related

Can Flutter's PageView widget be implemented for a just selected section of the screen instead of the entire screen?

Would it be possible to use the PageView widget just for the contents within Expanded widget in the code below? Essentially trying to swipe right for the items only within the Expanded widget instead of the entire screen.
class _MyHomeScreenState extends State<MyHomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
Container(),
Container(),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Container(),
Container(),
ListView.builder(itemBuilder: itemBuilder),
],
),
),
),
],
),
);
}
}
By doing this code below using the PageView widget, I get this error 'Horizontal viewport was given unbounded height'.
class _MyHomeScreenState extends State<MyHomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
Container(),
Container(),
PageView(
children: [
Container(
child: Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Container(),
Container(),
ListView.builder(itemBuilder: itemBuilder),
],
),
),
),
),
Container(),
],
),
],
),
);
}
}
You should wrap the pageview inside expanded. you are using an expanded inside pageview
This should fix the issue

How to create a button in flutter that always sticks to the bottom of the page?

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"),
);
}

How to make list view in card flutter

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

Flutter - Animate change on height when hide one of Column children

I have two children inside Column widget, the first one is simple Container and the second on is Expanded widget.
User can hide/show the first Container. In this case, I need to apply animation on both widgets, so the height of first container should be reduced automatically and the second widget should be increased gradually until fill the whole space.
I tested to use AnimatedContainer, but it needs to specify its height after and before, which is not known to me.
Any suggestion please?
class ViewerPage extends StatefulWidget {
#override
_ViewerPageState createState() => _ViewerPageState();
}
class _ViewerPageState extends State<ViewerPage> {
bool visible = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Example"),
),
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.show_chart),
onPressed: () {
setState(() {
visible = !visible;
});
},
),
],
),
),
body: Container(
child: Column(
children: <Widget>[
Visibility(
visible: visible,
child: Container(
child: Text("This Container can be visible or hidden"),
color: Colors.red),
),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) => Text("Item ..."),
itemCount: 20,
),
),
],
),
),
);
}
}
Simple, use AnimatedSize, and remove Visibility. AnimatedSize calculates height on its own. so u don't need to know size before and after.
Just pass null for dynamic height and 0 for non visibility. AnimatedSize will take care of the animation
height: visible? null : 0.0,
here, I changed your code a bit. It works fine now.
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> with SingleTickerProviderStateMixin{
bool visible = true;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Example"),
),
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.show_chart),
onPressed: () {
setState(() {
visible = !visible;
});
},
),
],
),
),
body: Container(
child: Column(
children: <Widget>[
AnimatedSize(
duration: Duration(seconds: 1),
child: Container(
height: visible? null : 0.0,
child: Text("This Container can be visible or hidden"),
color: Colors.red
),
vsync: this,
),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) => Text("Item ..."),
itemCount: 20,
),
),
],
),
),
);
}
}
The accepted solution technically didn't hide the item, it was just collapsed to height of zero, I had a situation where a widget (Icon) appears when the ListView sibling is swiped down.
I recommend the following solution:
AnimatedSize(
duration: const Duration(milliseconds: 500),
child: visible ? Container( child: Text("This Container can be visible or hidden"), color: Colors.red) : const SizedBox(),),

Can't get icon & text to appear

I can't seem to get icon button to appear with text next to it. Should look like:
I am following the introduction tutorial in Udacity. Still trying to get my head around all of the correct formatting, widgets, etc
Code:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: "Category List",
home: Scaffold(
appBar: AppBar(
title: Text('This is a list item'),
),
body: Category(),
),
),
);
}
class Category extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Material(
child: Container(
child: Padding(
padding: EdgeInsets.all(16.0),
child: InkWell(
onTap: () => {},
child: Row(
children: <Widget>[
Icon(Icons.access_alarms),
Text('Click'),
],
),
),
),
),
);
}
}
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: "Category List",
home: Scaffold(
appBar: AppBar(
title: Text('This is a list item'),
),
body: Category(),
),
),
);
}
class Category extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Material(
child: Container(
decoration:BoxDecoration(
color:Colors.green.withOpacity(0.4),
border:Border.all(),
),
child: Padding(
padding: EdgeInsets.all(16.0),
child: InkWell(
onTap: () => {},
child: Row(
children: <Widget>[
Icon(Icons.access_alarms),
Text('Click'),
],
),
),
),
),
);
}
}
have you tried to wrap your icons and text using Expanded() widget?