Flutter listview always expands to available width - flutter

What I need is green box should end where the text ends.
Here's my code
Widget buildFlexible() {
return Flexible(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: [
MessageBubble(title: 'Test1'),
MessageBubble(title: 'Test2'),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
Row(
children: [
buildFlexible(),
],
),
],
),
);
}
class MessageBubble extends StatelessWidget {
final String title;
MessageBubble({required this.title});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Material(
child: Text(title),
color: Colors.lightGreenAccent,
// elevation: 5.0,
),
);
}
}

Wrap your Padding widget from your MessageBubble class with the Wrap() widget
So, the final code for the MessageBubble should be:
class MessageBubble extends StatelessWidget {
final String title;
MessageBubble({required this.title});
#override
Widget build(BuildContext context) {
return Wrap(children: [
Padding(
padding: EdgeInsets.all(10.0),
child: Material(
child: Text(title),
color: Colors.lightGreenAccent,
// elevation: 5.0,
),
)
]);
}
}
Alternatively, you can achieve the same result with just using a Container widget and by removing the Material widget and the Padding widget as:
Wrap(children: [
Container(
padding: EdgeInsets.all(10.0),
child: Text('hi'),
color: Colors.lightGreenAccent,
)
])
Instead of:
Wrap(children: [
Padding(
padding: EdgeInsets.all(10.0),
child: Material(
child: Text(title),
color: Colors.lightGreenAccent,
// elevation: 5.0,
),
)
]);

Related

Widget scrolls under cupertino sliver navigation bar

When using the cupertino sliver navigation bar, the body scrolls under it.
I tried using nested scroll view but even that resulted in the same behavior
class MainScreen extends StatefulWidget {
const MainScreen({Key? key}) : super(key: key);
#override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: CustomScrollView(
slivers: [
CupertinoSliverNavigationBar(
brightness: Brightness.dark,
padding: EdgeInsetsDirectional.zero,
largeTitle: Text(
'Tasks',
style: appBarTextStyle,
),
trailing: CupertinoButton(
onPressed: () {}, child: primaryIcon(Icons.search)),
leading: CupertinoButton(
onPressed: () {}, child: primaryIcon(Icons.menu)),
),
SliverFillRemaining(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(
horizontal: 15.0, vertical: 15.0)
: const EdgeInsets.symmetric(
horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
filteredWidget(
context,
'Scheduled',
'No scheduled tasks',
arrayController.scheduledTodos,
Icons.schedule),
filteredWidget(
context,
'Today',
'Schedule a task for today',
arrayController.todayTodos,
Icons.calendar_today),
],
),
const SizedBox(
height: 20.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
filteredWidget(
context,
'Completed',
'No completed tasks',
arrayController.doneTodos,
Icons.done_rounded),
filteredWidget(context, 'All', 'No tasks yet',
arrayController.allTodos, Icons.task)
],
),
],
)),
)
],
),
);
}
}
Here is the full code on Github
Reproducible example:
import 'package:flutter/cupertino.dart';
void main() => runApp(const SliverNavBarApp());
class SliverNavBarApp extends StatelessWidget {
const SliverNavBarApp({super.key});
#override
Widget build(BuildContext context) {
return const CupertinoApp(
theme: CupertinoThemeData(brightness: Brightness.light),
home: SliverNavBarExample(),
);
}
}
class SliverNavBarExample extends StatelessWidget {
const SliverNavBarExample({super.key});
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
// A ScrollView that creates custom scroll effects using slivers.
child: CustomScrollView(
// A list of sliver widgets.
slivers: <Widget>[
const CupertinoSliverNavigationBar(
leading: Icon(CupertinoIcons.person_2),
// This title is visible in both collapsed and expanded states.
// When the "middle" parameter is omitted, the widget provided
// in the "largeTitle" parameter is used instead in the collapsed state.
largeTitle: Text('Contacts'),
trailing: Icon(CupertinoIcons.add_circled),
),
// This widget fills the remaining space in the viewport.
// Drag the scrollable area to collapse the CupertinoSliverNavigationBar.
SliverFillRemaining(
child: Container(
height: 100.0,
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(
horizontal: 15.0, vertical: 15.0)
: const EdgeInsets.symmetric(
horizontal: 35.0, vertical: 15.0),
),
),
],
),
);
}
}

How to remove padding of MaterialBanner?

I want to remove the following blue padding from MaterialBanner widget, but it doesn't seem to be customizable. I want to insert an image in the red region.
I looked into MaterialBanner for using across Scaffold widgets because ScaffoldMessenger doesn't allow me to insert widgets other than MaterialBanner.
Is there any suggestion?
dartpad.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: JustBanner())));
}
class JustBanner extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _JustBannerState();
}
}
class _JustBannerState extends State<JustBanner> {
#override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
final messenger = ScaffoldMessenger.of(context);
messenger.clearMaterialBanners();
messenger.showMaterialBanner(MaterialBanner(
padding: EdgeInsets.zero,
leadingPadding: EdgeInsets.zero,
leading: const SizedBox.shrink(),
backgroundColor: Colors.blue,
content: Container(
color: Colors.red,
width: 200,
height: 50,
),
actions: const [SizedBox.shrink()]));
},
child: const Text('Banner')),
],
);
}
}
Container(
width: MediaQuery.of(context).size.width,
child: MaterialBanner(
content: Text('Hello'),
actions: [
Icon(Icons.add),
],
),
),
Its no possible without copy and re-create the class, buttonBar always appear:
final Widget buttonBar = Container( // <-- problematic widget
alignment: AlignmentDirectional.centerEnd,
constraints: const BoxConstraints(minHeight: 52.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: OverflowBar(
overflowAlignment: widget.overflowAlignment,
spacing: 8,
children: widget.actions,
),
);
final double elevation = widget.elevation ?? bannerTheme.elevation ?? 0.0;
final Color backgroundColor = widget.backgroundColor
?? bannerTheme.backgroundColor
?? theme.colorScheme.surface;
final TextStyle? textStyle = widget.contentTextStyle
?? bannerTheme.contentTextStyle
?? theme.textTheme.bodyText2;
Widget materialBanner = Container(
margin: EdgeInsets.only(bottom: elevation > 0 ? 10.0 : 0.0),
child: Material(
elevation: elevation,
color: backgroundColor,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: padding,
child: Row(
children: <Widget>[
if (widget.leading != null)
Padding(
padding: leadingPadding,
child: widget.leading,
),
Expanded(
child: DefaultTextStyle(
style: textStyle!,
child: widget.content,
),
),
if (isSingleRow)
buttonBar, // <----- here
],
),
),
if (!isSingleRow)
buttonBar, // <----- here
if (elevation == 0)
const Divider(height: 0),
],
),
),
);

How can I build 2 lined ListView.builder in Flutter

Can anyone explain me how can I build widget as ListView builder with 2 lines of items. I got an example of this type, you can check out it by the picture below:
An option is to use the Wrap widget with direction set to horizontal.
#override
Widget build(BuildContext context) {
final lorem = [
'accusamus',
'dignissimos',
'ducimus',
'blanditiis',
'praesentium',
'voluptatum'
];
return Container(
height: 100,
width: 250,
child: Wrap(
direction: Axis.horizontal,
children: List.generate(
lorem.length,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Text(lorem[index]),
),
),
),
);
}
This snippet should help you.
You can try it at https://dartpad.dev/028daa76945938f0e5c14aea6a8bf84b?null_safety=true
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SizedBox(
width: 500.0,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: ['English', 'Russian', 'Spanish']
.map((language) => LanguageButton(
language: language,
))
.toList(),
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: ['Some really long language', 'French', 'German']
.map((language) => LanguageButton(
language: language,
))
.toList(),
),
],
),
);
}
}
class LanguageButton extends StatelessWidget {
final String language;
const LanguageButton({Key? key, required this.language}) : super(key: key);
#override
Widget build(BuildContext context) {
return OutlinedButton(
style: OutlinedButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(30),
),
),
),
onPressed: () {
// TODO
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 8.0),
child: Text(language),
),
);
}
}
I used a Column instead of a ListView.builder. Maybe that's good enough for what you need. The gist is to have each line as a Row and set the mainAxisAlignment to spaceBetween.

Scrollable Listview issue - Flutter

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()
)
]
)
)
);
}
}

Flutter showing hasSize error when wrap container in column

I am getting an error when I wrap my container in the column widget. I need 2 containers in a column but when I wrap it in column widget it's showing this error
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
Showing this in Column line error
Here is my code
class _PlaceListState extends State<PlaceList> {
final List _places = [
{'name': 'Hunza', 'where': 'Gilgit Baltistan'},
{'name': 'Skardu' ,'where': 'Gilgit Baltistan'},
{'name': 'Murree', 'where': 'Gilgit Baltistan'},
];
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(
margin: EdgeInsets.only(left: 40),
width: MediaQuery.of(context).size.width * 0.5,
child: ListView.builder(
itemCount: _places.length,
itemBuilder: (ctx, int index) {
return Container(
padding: EdgeInsets.only(top: 50),
child: Column(
children: <Widget>[
Text(_places[index]['name'], style: TextStyle(fontSize: 20),),
Container(
padding: EdgeInsets.only(top: 20),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Card(
elevation: 40.0,
child: Container(
width: 200,
child: Image(image: AssetImage('assets/images/500place.jpg')),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 7),
child: Row(
children: <Widget>[
Icon(Icons.favorite_border, size: 20),
Spacer(),
Text(
_places[index]['where'],
),
],
)
),
],
),
);
}),
)
],);
}
}
The screen output i use Navigation rale so that's why I set the width and its working fine without Column widget
You can copy paste run full code below
Step 1: Provide height when use PlaceList() , you can use Expanded(child: PlaceList())
Step 2: add shrinkWrap: true for ListView
Step 3: Use Expaneded flex to provide height for Container() 1 and 2
Column(
children: <Widget>[
Expanded(
flex: 3,
...
Expanded(
flex: 1,
child: Center(child: Container(child: Text("Second Container"))))
working demo
full code
import 'package:flutter/cupertino.dart';
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: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState 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: <Widget>[
Expanded(child: PlaceList()),
],
),
),
);
}
}
class PlaceList extends StatefulWidget {
#override
_PlaceListState createState() => _PlaceListState();
}
class _PlaceListState extends State<PlaceList> {
final List _places = [
{'name': 'Hunza', 'where': 'Gilgit Baltistan'},
{'name': 'Skardu', 'where': 'Gilgit Baltistan'},
{'name': 'Murree', 'where': 'Gilgit Baltistan'},
{'name': 'abc', 'where': 'def'},
];
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
margin: EdgeInsets.only(left: 40),
width: MediaQuery.of(context).size.width * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: _places.length,
itemBuilder: (ctx, int index) {
return Container(
padding: EdgeInsets.only(top: 50),
child: Column(
children: <Widget>[
Text(
_places[index]['name'],
style: TextStyle(fontSize: 20),
),
Container(
padding: EdgeInsets.only(top: 20),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Card(
elevation: 40.0,
child: Container(
width: 200,
child: Image(
image: AssetImage(
'assets/images/500place.jpg')),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 7),
child: Row(
children: <Widget>[
Icon(Icons.favorite_border, size: 20),
Spacer(),
Text(
_places[index]['where'],
),
],
)),
],
),
);
}),
),
),
Expanded(
flex: 1,
child: Center(child: Container(child: Text("Second Container"))))
],
);
}
}
try adding height: // define height in double to your container
Add the shrinkWrap property to your ListView as seen below:
child: ListView.builder(
itemCount: _places.length,
shrinkWrap: true,
itemBuilder: (ctx, int index) {
return Container(...
Setting the shrinkWrap to true would result in the list wrapping its content and be as big as its children permits
You could also add a height to your Container
return Container(
height: 90,
...
)