Flexible widgets not rendering inside Column - flutter

I need to word-wrap some text and have been reading how Flexible and Expanded help make that happen. My problem is the rendering breaks when I put the resulting widgets in a Column. I read that you need to wrap parent columns in Expanded widgets, too, but that gave the same broken result?
Here's a text version of what I'm after
The DartPad code below produces that, but when the commented Column is uncommented, no text is rendered?
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeDat.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return
// Column( children: [ // <- Uncommenting Column breaks rendering
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('[Avatar]'),
SizedBox(width: 10),
Expanded(
child: Column(mainAxisAlignment: MainAxisAlignment.start, children: [
Flexible(
child: Text(
'Really Really Really Really Really Really Really Really '
'Really Really Really Really Really Really Long Heading'),
),
Flexible(
child: Text(
'Really Really Really Really Really Really Really Really '
'Really Really Really Really Really Really Long Text'),
),
]),
),
SizedBox(width: 10),
Text('[Button]'),
// ]),
],
);
}
}

You can solve the issue just by wrapping the Row with an Expanded.

try this
Flexible(fit: FlexFit.loose,child:.....)

Related

In Flutter, why Scaffold's body can't directly use Row()?

If I use Row() instead of Center(), it will not be displayed,just blank.
I expect a music player like layout.
Make 2 Row, the 1st Row contain "LeftMenu" and "Expanded Container" for content .
Putting this in scaffold gives you the left menu:
drawer: const Drawer(
child: Text("Left Menu")
),
Putting this inside scaffold body works. Expanded and a row:
Column(
children: [
Expanded(
child: Container(
color: Colors.green,
child: const Center(child: Text("1")),
)
),
Row(
children: const [
Text("1"),
SizedBox(width: 10),
Text("2"),
],
),
],
)
If you replace center with row, it probably displays but in the top left corner and not middle. Try to wrap your Row with Center and it should display in the middle. For the row you need to add a mainAxisAlignment.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center (child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:[ Text('Left menu'),Text('Place container here')]
),),
),
);
}
}
This is actually the wrong question.
The real problem is: if the ListView is nested by Column, Row, it will not be displayed.
You need to use Expanded or Container on the outside and then nest it with Colmn or Row.

Alignment properties doesn't work so I use empty expanded widget

I want make text to the right, what am I doing so far
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _judul = 'Private Chat';
static var _warnaTema = Colors.pink[100];
Widget _dummyExpanded() {
return Expanded(
child: Container(), //contain empty data,
); //just for fill remaining space
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _judul,
theme: ThemeData(
primaryColor: _warnaTema,
),
home: Column(
children: [
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 1'),
],
),
),
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 2'),
],
),
)
],
),
);
}
}
The layout output is what I expected (the text is in right), however there's unneeded code.
As you see I use unnecessary method _dummyExpanded to fill
available space which it's just expanded with empty container. Of course it will be hard to read since there are many nested row and column, how I remove that unneeded method without loss layout output what I expect?
I believe I should have use alignment but I don't know how to
Method 1.
Container(
child: Row(
mainAxisAlignment:MainAxisAlignment.end,
children: [
Text('this is real data 2'),
],
),
)
Method 2.
I prefer this method, You can wrap text with this method.
You can also use Flexible widget instead of Expanded
Container(
child: Row(
children: [
Expanded(child: Text('this is real data 2', textAlign:TextAlign.end )),
],
),
)
Method 3.
If you have only Text widgets as children of Column widget then you can set crossAxisAlignment: CrossAxisAlignment.end, for your parent Column widget.

How to place Row elements' centers evenly (not using Expanded-s)

I tried my best to summarize what I want in the title, but here is a more detailed explanation:
Widgets' centers should be placed evenly throughout the row.
A larger widget should be able to extend into the "personal space" of a smaller one.
When it would overflow, overflow should start on the bigger items, cutting into the smaller ones later.
Here's an illustration:
Behavior with Expandeds:
Everything fits
Longest item is overflowing - The problem with this is that the longest text would easily fit if it could extend into the boundary of the shorter texts next to it.
How it should work:
Please notice: The boxes are not Expanded, but the centers of them are evenly placed (not by themselves, but as if they were the centers of Expandeds). As opposed to just laying them out with usual MainAxisAlignment options; neither of those ensures that the centers are evenly placed, a longer text can push the shorter ones to one side. (Illustraion of what I don't want)
Everything fits
Longest text extends into the area of the shorter ones
When two boxes would touch, overflow the longer one
Extreme case - default to even sizes
This may be asking a lot, but I think there should be a way of achieving these, what's more, I think this should be the default way rows with texts work.
Any help on any sub-request is much appreciated.
Edit: I understand that everything I described is pretty complicated when put together. I would be happy to know a way to just simply place center lines evenly, with different width boxes (and no, spaceEvenly doesn't do this). Overflowing behavior can be a different question.
Have you tried mainAxisAlignment: MainAxisAlignment.spaceEvenly? Then you can play with the padding. It seems that you would also like to make your UI responsive, try the LayoutBuilder class. The documentation can be found here https://flutter.dev/docs/development/ui/layout/responsive .
First of all use 3 Expanded() for taking spaces for 3 Text() Widgets after that you can align your text at center using a container. Hope this solution will meet your requirement.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Lorem', style: TextStyle(fontSize: 24),),
),
),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Lorem ispum', style: TextStyle(fontSize: 24),),
),
),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Lorem', style: TextStyle(fontSize: 24),),
),
),
]
);
}
}

Flutter - How can I make a square widget take up its maximum possible space in a row?

I have a CustomPaint that needs to be a 1:1 square, and I need to put this in a Row. The horizontal and vertical space available can vary, so I need both the length and width of the square to be the smallest maximum constraint.
How can I achieve this behaviour?
I've tried using LayoutBuilder for this:
Row(
children: [
...,
LayoutBuilder(
builder: (context, constraints) {
final size = min(constraints.maxWidth, constraints.maxHeight);
return SizedBox(
width: size,
height: Size,
child: CustomPaint(...),
),
},
),
]
),
This, however, doesn't work, because Row provides unbounded horizontal constraints (maxWidth == double.infinity). Using the FittedBox widget also fails for the same reason.
Wrapping the LayoutBuilder in an Expanded widget provides it with a bounded maximum width, but I need to have another widget next to it in the Row, so this is not appropriate. Flexible behaves like Expanded in this case, as well.
I think you can get what you want from the AspectRatio widget... if you tell it 1:1, then it tries to make a square unless completely not possible.
Please try the code below, using Align widget restrains the widget to a square :
import 'package:flutter/material.dart';
import 'dart:math';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
flex: 1,
child: Container(),
),
Expanded(
flex: 2,
child: LayoutBuilder(
builder: (context, constraints) {
final size = min(constraints.maxWidth, constraints.maxHeight);
return Align(
alignment: Alignment.centerRight,
child: Container(
height: size,
width: size,
color: Colors.amber,
),
);
},
),
),
// Expanded(
// flex: 1,
// child: Container(),
// ),
],
);
}
}
I ended up working this issue by moving the responsibility of keeping the widget square up the tree. Widgets that were using the square widget knew more about what other things they were showing and were more capable of giving it the right constraints.

Could not find the correct Provider

I'm new to using flutter and i was trying to implement a covid 19 tracker of cases in the world and i got this error when creating a custom widget to display number of cases , can anyone help me figure out the solution to this exactly as i have been trying to fix it for hours now.
This is the exception caught by the widgets library:
Error: Could not find the correct Provider above this NewCasesCard Widget
To fix, please:
Ensure the Provider is an ancestor to this NewCasesCard Widget
Provide types to Provider
Provide types to Consumer
Provide types to Provider.of()
Ensure the correct context is being used.
If none of these solutions work, please file a bug at:
https://github.com/rrousselGit/provider/issues
Here is the code:
import 'package:stay_safe/Providers/AppBrain.dart';
import 'package:stay_safe/utils/theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class NewCasesCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return getCard(context);
}
Widget getCard(context){
if (Provider.of<AppBrain>(context).isloading2)
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SpinKitPumpingHeart(color: AppTheme().kcolors[0],),
),
);
else {
final countryInfo = Provider.of<AppBrain>(context).countryStats['countrydata'][0];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 0.5,
color: Colors.white70,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('New Cases Today',style: GoogleFonts.cabin(fontSize: 25),),
),
SizedBox(height: 8,),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
StatIcon(countryInfo['total_active_cases'], 'Active', AppTheme().kcolors[0]),
StatIcon(countryInfo['total_new_cases_today'], 'New Cases', AppTheme().kcolors[2]),
StatIcon(countryInfo['total_new_deaths_today'], 'Deaths', AppTheme().kcolors[1])
],),
)
],
),
),
);
}
}
}
Widget StatIcon(int count,String type,Color color){
return Column(
children: <Widget>[
Text(count.toString(),style: GoogleFonts.cabin(color: color,fontWeight: FontWeight.bold,fontSize: 20),),
Text(type,style: GoogleFonts.cabin(color: color,fontWeight: FontWeight.bold,fontSize: 20),),
],
);
}
The issue looks like you have created the AppBrain provider in a different part of your widget tree to NewCasesCard, so when NewCasesCard attempts to find the provider by searching the tree it cannot. You need to make sure that the AppBrain provider is above NewCasesCard somewhere in the widget tree. So for example in the screen that includes this widget you could have:
class NewCasesScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Provider<AppBrain>(
create: (_) => AppBrain(),
child: Scaffold(
body: ListView(
children: [
NewCasesCard(),
...
]
),
),
);
}
Alternatively you could initialise the provider at the top of your app since, from the name, it looks like it is used throughout. For this you could utilise the MultiProvider and have:
(Example taken from the package readme)
void main {
runApp(MultiProvider(
providers: [
Provider<AppBrain>(create: (_) => AppBrain()),
Provider<SomethingElse>(create: (_) => SomethingElse()),
],
child: MaterialApp(...),
));
}
This way you can be sure that the provider will always be found.