I am using ListView.builder function to create a list of items. However, the space between each item in iOS is huge (screenshot). Do you know how to remove item? It seems it is by default, because I do not adding it.
code:
ListView:
return Scaffold(
body: ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
final model = data[index];
if (model.path.isEmpty)
return Divider(color: Colors.grey[500], indent: 40.0);
else
return ItemMenu(model.path, model.name);
}),
);
Item:
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Image.asset(path, width: 100, height: 100,color: Colors.grey[500]),
Text(name, style: MyTextTheme().getLightSmallGrey().copyWith(fontSize: 20.0, fontWeight: FontWeight.w700))
],
);
If you are using a ListTile widgets as your ListView items, you can add the dense = true option:
ListView(
children: [
ListTile(
dense: true,
...
),
ListTile(
dense: true,
...
),
]
),
Most of the answers recommended using dense: true but that just made the text smaller in my case and did not actually reduce the spacing between List Items.
Solution:
Use visualDensity property instead within the ListTile.
Code Example:
visualDensity:VisualDensity(horizontal: 0, vertical: -4),
i just resolved that issue but within an image network with "fit" property: Boxfit.cover/fill
Related
I am trying to create a Draft Page Screen for a blog app ,which has a Textfield and a close icon for closing it and a Publish Text for publishing it .I have given the Publish a Close icon in a row so even if scroll down after typing the row should remain fixed at the top .But how can I make the row widget fixed at the top of the body ?
This is my code:
ListView(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
InkWell(
child: Icon(Icons.close_sharp),
onTap: () {
Navigator.pop(context);
},
),
Text("Publish"),
],
),
TextField(
autofocus: true,
decoration: new InputDecoration(
border: InputBorder.none),
keyboardType: TextInputType.multiline,
maxLines: null,
cursorColor: Color(0xff057009),
cursorHeight: 30,
),
],
),
Try this code this will do the trick.
Scaffold(
appBar: AppBar(
title: const Text('Blog View'),
),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
InkWell(
child: const Icon(Icons.close_sharp),
onTap: () {
Navigator.pop(context);
},
),
const Text("Publish"),
],
),
const Expanded(
child: TextField(
autofocus: true,
decoration: InputDecoration(border: InputBorder.none),
keyboardType: TextInputType.multiline,
maxLines: null,
cursorColor: Color(0xff057009),
cursorHeight: 30,
),
),
],
),
);
Your row must be outside the list. You can make the list scrollable as well, but just make it outside the main list.
Here is an example:
Column with a preferred height, for example media query . size . height - > [
SizedBox height: the height you want to show of the row
-> SingleChildScrollView -> your Row with the possibly overflowing text
...Your other children in a scrollable view
]
I am trying to create one Grid View page with Cards as list elements and the last of the cards are getting cut from the bottom. The following are relevant code snippets:
createListBody.dart
List<String> services = [
'Demo1',
'Demo2',
'Demo3',
'Demo4',
'Demo5',
'Demo6',
'Demo7',
'Demo8',
'Demo9',
'Demo10',
];
#override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
children: services.map((String serviceName){
return Container(
child:Card(
color: Colors.grey[500],
elevation: 15,
semanticContainer: true,
shadowColor: palletFuchsia,
shape: CircleBorder(),
child: InkWell(
onTap: (){
print("Tapped "+serviceName);
},
child: Center(
child: Text(
serviceName,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25
),
),
),
),
)
);
}).toList(),
),
);
}
listScreen.dart
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: palletWhiteDrawer,
drawer: Theme(
data: Theme.of(context).copyWith(
canvasColor: palletYellowDrawer,
),
child: CreatDrawerWidget(),
),
appBar: CreateAppBar(),
body:GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ServiceListBody()
],
)
),
),
);
}
Screenshot
I am completely new to flutter so, sorry if there is some silly mistake. But any help would be useful.
Thank you for your time!
Just for exploring, you can do height: MediaQuery.of(context).size.height *2, It shouldn't get cut anymore right?
Solution 1
Your telling your container a given height which is fix for the moment, no matter how many items you got inside your ListView.
You can for example use ConstrainedBox with shrinkWrap:true and manage your max height
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200, minHeight: 56.0),
child: ListView.builder(
shrinkWrap: true,
...
more info: https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html
Solution 2
use Slivers, they are dynamic.
For this you need to customize your structure a little bit. You wrap everything with a CustomScrollView(), SliverToBoxAdapter() for fixed elements and SliverList() for dynamic ones, makes it work like a charm.
Example using CustomScrollView and SliverToBoxAdapter:
return SafeArea(
child: CustomScrollView(
//scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
slivers: <Widget>[
// Place sliver widgets here
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(25, 30, 25, 20),
child: SizedBox(
height: 299,
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
...
You can define the height with the SizedBox height. Also you can apply nice effects to your whole View on the CustomScrollView
Example Sliverlist:
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, index) => ChangeNotifierProvider.value(
value: list[index],
child: GestureDetector(
onTap: () {}),
childCount: list.length,
)),
Infos about slivers: https://medium.com/flutterdevs/explore-slivers-in-flutter-d44073bffdf6
The GridView Widget itself is Scrollable , So you don't have to wrap it with a Column and SingleChildScrollView Widget...
You can now simply scroll down if the Circles goes out of the screen
If you wish all the circles to fit in the screen.. You'll have to use
var mobileHeight = MediaQuery.of(context).size.height
And then the height of each circles will be mobileHeight divided by the no. of circles vertically.
I am trying to have a ListView with one single scroll. I want to be able to scroll down and see every widget. Currently, I have multiple widgets before a GridView. The problem with this is that the GridView has its own scroll. A good example of what I want is similar to the Instagram profile page. When you scroll down in the Instagram profile page, every element scrolls down. There are no nested scrolls.
This is my current code:
body: ListView(
children: <Widget>[
...
...
Container(
child: GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
children: List.generate(100, (index) {
return Container(
alignment: Alignment.center,
margin: EdgeInsets.all(3.0),
height: MediaQuery.of(context).size.height,
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image:'https://picsum.photos/${300}/${300}/',
),
);
}),
),
)
]
)
There's Nested Scrolled Widgets, the CustomScrollView which takes Slivers to achieve what you're looking for. SliverGrid and SliverList are the ones you need to achieve your goal:
Widget sliverScroll() {
return CustomScrollView(
slivers: <Widget>[
SliverGrid(
delegate: SliverChildBuilderDelegate((context, index) {
return Container();
}, childCount: 9),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Container();
}, childCount: 6),
),
],
);
}
You can customize as you wish, changing the order or it, item count, etc
I am trying to place an ExpansionTile with a horizontal GridView child in a container. See below for code. I get the error message 'Horizontal viewport was given unbounded height.'
I don't want to specify the height of ExpansionTile or GridView explicitly, but rather have it calculated from the Expanded widget and the children of GridView.
I've tried setting 'shrinkWrap: true' in GridView as suggested here with no success. I also tried wrapping GridView in Flexible based on this answer which gives me the error 'RenderFlex children have non-zero flex but incoming height constraints are unbounded.'
I think the problem is with how I'm using GridView, but I'm new to Flutter and not really sure. Here is my code:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Title")),
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: ExpansionTile(
title: Text("Expandable"),
children: <Widget>[
GridView.count(
scrollDirection: Axis.horizontal,
crossAxisCount: 2,
children: <Widget>[
RawChip(label: Text("Hello")),
RawChip(label: Text("World")),
],
),
],
),
),
Expanded(
flex: 7,
child: Container(
color: Colors.blue
),
),
],
),
),
),
);
You can just add a height constraint to your GridView :
ExpansionTile(
title: Text("Expandable"),
children: <Widget>[
SizedBox(
height: 200.0,
child: GridView.count(
scrollDirection: Axis.horizontal,
crossAxisCount: 2,
children: <Widget>[
RawChip(label: Text("Hello")),
RawChip(label: Text("World")),
],
),
),
],
),
I have this code for a chat app that renders a series of messages. The thing is page is showing ok, but when trying to send a message rendering overflow appears. It's like my input is going all the way up instead of setting itself over my displayed keyboard.
This is my code for rendering the page
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: ListView.builder(
itemBuilder: (_, index) => _messages[index],
itemCount: _messages.length,
//El reverse hace que vaya de abajo hacia arriba
reverse: true,
padding: EdgeInsets.all(6.0),
),
),
Divider(
height: 1.0,
),
Container(
child: _buildComposer(),
decoration: BoxDecoration(color: Theme.of(context).cardColor),
)
],
),
);
And here I have my code for the input where think the mistake is
Widget _buildComposer() {
return IconTheme(
data: IconThemeData(color: Theme.of(context).accentColor),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 9.0),
child: Row(
// mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: TextField(
controller: _textController,
onChanged: (String texto) {
setState(() {
_isWriting = texto.length > 0;
});
},
onSubmitted: _enviarMensaje,
decoration:
InputDecoration.collapsed(hintText: "Envie un mensaje!"),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 3.0),
child: IconButton(
icon: Icon(Icons.message),
onPressed: _isWriting
? () => _enviarMensaje(_textController.text)
: null,
),
)
],
),
),
);
}
Here are my print captures for initial rendering, after clicking inside the input to write some message
Here's my log, and it's supposed to be easy to understand the approach I should take but I'm not having any luck with it.
FYI: I have already tried this approach but did not seem to work
StackOverflow answer on rendering
I have already gone through flutter.io docs but I'm not understanding the whole listview theory. If you have some insights I would appreciate them as well so I can deeply understand how it behaves.
resizeToAvoidBottomPadding: false might help.. have a look here
As #diegoveloper's comment, it will not resize which means it will not show content behind keyboard. Based on your use case you can choose option 1 or 2 in the above link