Align Materials to same widths and heights without a Table - flutter

I created a material for my app which should enclose some text. It looks like this:
Sometimes, there is overflowing text. With a flexible it looks like this:
And I also want it to align like in a Table. Without alignment to the others it looks like this:
The Border between the colors should be at the same position for all of those elements so it looks clean.
How can I achieve all of this? The Flexible Widget throws a WrongParent Exception when Put into a Table.
My Code:
import 'dart:math';
import 'package:flutter/material.dart';
import 'nook_constants.dart';
class NookTable extends StatelessWidget {
final double width;
final double height;
final EdgeInsets margin;
final Widget child;
final String title;
final String text;
final String font;
NookTable({
this.width,
this.height,
this.margin: nookDefaultMargin,
this.child,
this.title,
this.text,
this.font
});
final cell = (Widget widget) => Padding(
padding: EdgeInsets.only(left: 15, top: 5, bottom: 5, right: 15),
child: widget,
);
#override
Widget build(BuildContext context) {
var margin = EdgeInsets.only(
left: this.margin?.left ?? 0.0,
right: this.margin?.right ?? 0.0,
top: this.margin?.top ?? 0.0,
bottom: max(2, this.margin?.bottom ?? 0.0),
);
return Container(
width: width,
height: height,
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.only(left: 15, top: 5, bottom: 5, right: 15),
decoration: BoxDecoration(
color: Colors.transparent,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
NookTitleDetails(text: title, width: width,),
NookTextDetails(text: text,),
],
),
);
}
}
class NookTextDetails extends StatelessWidget {
final String text;
final String font;
NookTextDetails({
this.text,
this.font
});
final cell = (Widget widget) => Padding(
padding: EdgeInsets.only(left: 15, top: 5, bottom: 5, right: 15),
child: widget,
);
#override
Widget build(BuildContext context) {
return Flexible(
child: Material(
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.only(bottomRight: Radius.circular(25), topRight: Radius.circular(25)),
color: nookBeige,
child: cell(Text(text))
),
);
}
}
class NookTitleDetails extends StatelessWidget {
final String text;
final String font;
final double width;
NookTitleDetails({
this.text,
this.font,
this.width
});
final cell = (Widget widget) => Padding(
padding: EdgeInsets.only(left: 15, top: 5, bottom: 5, right: 15),
child: widget,
);
#override
Widget build(BuildContext context) {
return Container(
width: width,
child: Material(
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(25), topLeft: Radius.circular(25)),
color: nooklightGreen,
child: cell(Text(text, style: TextStyle(color: nookWhite)))
),
);
}
}

Container(
decoration: BoxDecoration(
color: Colors.lime,
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 1,
child: Stack(
children: <Widget>[Container(
width: 100,
padding: EdgeInsets.all(5),
child: Text('Fundort',textAlign: TextAlign.center,))],
)),
Expanded(
flex: 4,
child: Container(
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.horizontal(right:Radius.circular(10))
),
padding: EdgeInsets.all(10),
child: Text('Sign in with FacebookSign in with Facebook',
style: TextStyle(fontSize: 18, color: Colors.white)),
),
)
]),
),

Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 0,
child: Container(
width:100,
child:Text('Text to the left')
)
),
Expanded(
flex: 4,
child:Text('Text to the right')
),
],
),

Related

Rounded corners and borders are not precise in Flutter

I would like to have a view like below:
My code is:
class SampleRoundedWidget extends StatelessWidget {
final imageUrl = 'test.png';
final domain = 'twitter.com';
final description = 'Sample description';
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: context.activeTheme.bg6),
borderRadius: BorderRadius.circular(_borderRadius),
),
margin: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_image(),
_divider(),
_domain(),
_description(),
],
),
);
}
Widget _image() {
return ClipRRect(
borderRadius: BorderRadius.only(topLeft: RadiusCircular(_borderRadius), topRight: RadiusCircular(_borderRadius)),
child: CachedNetworkImage(imageUrl: imageUrl),
);
}
Widget _divider() {
return Divider(height: 2);
}
Widget _domain() {
return Padding(
padding: const EdgeInsets.only(
right: 8.0,
left: 8.0,
top: 8.0,
bottom: 1.0,
),
child: Text(domain),
);
}
Widget _description() {
return Padding(
padding: const EdgeInsets.only(
right: 8.0,
left: 8.0,
top: 1.0,
bottom: 8.0,
),
child: Text(description),
);
}
final _borderRadius = 8.0;
}
However, I've noticed that corners are not precise:
Also, the divider has weird space:
Is it some kind of Flutter optimization when drawing? How I can make it more detailed?
Divider leaves the space, check height attribute. More details here

Flutter skeleton view shimmer view

I'm trying to achieve the skeleton view as shown in the attachment but couldn't get it exactly like shown, i have tried Shimmer package, the problem is gradient or mask width is more. Kindly help with sample for to achieve the same.
Used the shimmer: ^2.0.0
My ListView
return Padding(
padding: const EdgeInsets.only(top: 16),
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return ShimmerItem();
},
itemCount: 10,
),
);
ShimmerItem Widget:
class ShimmerItem extends StatelessWidget {
const ShimmerItem({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.only(left: 16, right: 16, bottom: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Theme.of(context).cardTheme.color,
child: Container(
margin: EdgeInsets.only(left: 16, bottom: 8, top: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(right: 32.0),
child: ShimmerWidget.rectangular(
height: 16,
width: MediaQuery.of(context).size.width * 0.9,
)),
Padding(
padding: const EdgeInsets.only(right: 32.0, top: 8),
child: ShimmerWidget.rectangular(
height: 16,
width: MediaQuery.of(context).size.width * 0.6,
),
),
Padding(
padding: const EdgeInsets.only(top: 16, bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
ShimmerWidget.rectangular(
height: 16,
width: MediaQuery.of(context).size.width * 0.4,
),
SizedBox(
width: 10,
),
ShimmerWidget.rectangular(
height: 16,
width: MediaQuery.of(context).size.width * 0.4,
),
],
),
),
],
),
),
);
}
}
ShimmerWidget Class:
class ShimmerWidget extends StatelessWidget {
final double width;
final double height;
final ShapeBorder shapeBorder;
const ShimmerWidget.rectangular(
{this.width = double.infinity, required this.height})
: this.shapeBorder = const RoundedRectangleBorder();
const ShimmerWidget.circular(
{this.width = double.infinity,
required this.height,
this.shapeBorder = const CircleBorder()});
#override
Widget build(BuildContext context) => Shimmer.fromColors(
baseColor:
ColorHelper.colorWithTransparency(AppColors.shimmer_bg_color,
100),
highlightColor:
ColorHelper.colorWithTransparency(AppColors.shimmer_color_dark,
20),
period: Duration(milliseconds: 1500),
child: Container(
width: width,
height: height,
decoration: ShapeDecoration(
color: AppColors.shimmer_bg_color,
shape: shapeBorder,
),
),
);
}
We can use LayoutBuilder for measurement, which is depending on parent size and perfect for this case.
To struct the same UI, I am just constructing the ShimmerItem widget, rest of widget will be same.
To get rounded border I am using ClipRRect with providing borderRadius.
Padding to control the sounded spacing and SizedBox to provide space on Column's children.
Used Row's mainAxisAlignment: MainAxisAlignment.spaceBetween,to separate last two shimmer widgets.
Resource about layout-basics.
class ShimmerItem extends StatelessWidget {
const ShimmerItem({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final _border = BorderRadius.circular(12);
final double _bHeight = 24;
return LayoutBuilder(
builder: (context, constraints) => Padding(
padding: const EdgeInsets.all(12.0), //outside the card
child: Container(
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
color: Colors.grey,
),
padding: const EdgeInsets.all(8), // inner padding
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//* top large two
ClipRRect(
borderRadius: _border,
child: ShimmerWidget.rectangular(
height: _bHeight,
width: constraints.maxWidth,
),
),
const SizedBox(height: 8),
ClipRRect(
borderRadius: _border,
child: ShimmerWidget.rectangular(
height: _bHeight * .75,
width: constraints.maxWidth,
),
),
const SizedBox(height: 8),
//3rd row
ClipRRect(
borderRadius: _border,
child: ShimmerWidget.rectangular(
height: _bHeight * .75,
width: constraints.maxWidth * 0.6,
),
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ClipRRect(
borderRadius: _border,
child: ShimmerWidget.rectangular(
height: _bHeight,
width: constraints.maxWidth * 0.4,
),
),
ClipRRect(
borderRadius: _border,
child: ShimmerWidget.rectangular(
height: _bHeight,
width: constraints.maxWidth * 0.4,
),
),
],
),
],
),
),
),
);
}
}
I am using demo color.
You need wrap all your child inside 1 bigger Shimmer wrapper to do that, not Shimmer on every small retangle.
I have project code for this in my laptop but im working afar, sorry.

excess white space at the end of my text in my widget

I have been trying a lot of ways to try to get rid of the excess space at the end of my sentence which is supposed to be unpredictable. does anyone know how to make sure the length of the widget ends at the end of the last text, especially when used with pageview or list view widget?. it works fine without the use of any scrollable widget but anytime I use a scrollable widget I have to add a height which makes it hard to define a boundary.
class FeedsDetailView extends StatelessWidget {
const FeedsDetailView({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final String text2 = lorem(paragraphs: 9, words: 500);
final String text3 = lorem(paragraphs: 10, words: 1000);
final String text4 = lorem(paragraphs: 8, words: 5000);
final String text5 = lorem(paragraphs: 12, words: 500);
final textList = [
text3,
text4,
text5,
];
return Scaffold(
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(top: 45),
child: Column(
children: [
Container(
height: 380,
width: double.maxFinite,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/night building.jpeg'),
fit: BoxFit.cover,
),
),
),
const SizedBox(height: 8),
Divider(
color: Theme.of(context).colorScheme.secondary,
indent: 50,
endIndent: 50,
),
Container(
height: double.maxFinite,
child: PageView.builder(
itemCount: textList.length + 1,
itemBuilder: ((context, index) {
if (index == 0) {
return Column(
children: [
const Text('bla bla bla'),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.only(left: 8, right: 8),
child: SizedBox(width: 350, child: Text(text3)),
),
],
);
} else {
return Column(
children: [
const Text('bla bla bla'),
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.only(left: 8, right: 8),
child: SizedBox(
width: 350,
child: Text(
textList[index - 1],
),
),
)
],
);
}
}),
),
)
],
),
),
),
);
}
}
I am also using the flutter_lorem package to generate long texts.
Remove this line
height: double.maxFinite,

In Flutter, how would I place a caption like a overlay on a ClipArt?

Please, take a look at the attached screenshots.
The left image is what I currently have. A ClipRect widget displaying a local image:
return Container(
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
width: 250,
height: 350,
child: ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset('assets/images/$image.jpg', fit: BoxFit.cover),
),
);
It's depicting on the right (red arrow) what I have in mind.
I suspect it would involve a Stack, a Positioned, and maybe an Opacity, but I don't know where to begin.
Try this:
return Container(
margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
width: 250,
height: 350,
child: Stack(children:[
ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset('assets/images/$image.jpg', fit: BoxFit.cover),
),
Positioned(
bottom: 0,
child: Container(
width: double.infinity,
height: 50.0,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white.withOpacity(0.5),
),
child: Text('blablabla'),
),
),
],
),
);
Stack will be what are you looking for , wrap your ClipArt with Stack and that's it
Thanks Jim,
Your response led me to a solution. For a Positioned widget to work, however, the enclosing Stack must contain only StatelessWidgets or StatefulWidgets and not RenderObjectWidgets like the ClipRRect I was originally using. I had to enclose the image in a StatelessWidget I called, StackImage.
class PicTab extends StatelessWidget {
const PicTab({Key key, #required this.name, #required this.state})
: super(key: key);
final String name;
final SubmodulesState state;
#override
Widget build(BuildContext context) {
//
String image;
if (name == null || name.isEmpty) {
image = 'river_bend';
} else {
image = name.trim();
}
final stackImage = StackImage(name: 'assets/images/$image.jpg');
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 3),
child: Stack(
children: [
stackImage,
Positioned(
bottom: 0,
child: Container(
width: stackImage.width,
height: stackImage.height * 0.3,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32),
color: Colors.white.withOpacity(0.5),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(''),
]),
),
),
],
),
);
}
}
class StackImage extends StatelessWidget {
const StackImage({
Key key,
#required this.name,
this.width = 250,
this.height = 250,
}) : super(key: key);
final String name;
final double width;
final double height;
#override
Container build(BuildContext context) => Container(
width: width,
height: height,
child: ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.asset(
name,
fit: BoxFit.cover,
),
),
);
}

Flutter - Container child doesn't take up full container

In the image below, I need to make the green child to take up all of the grey container on the left side, so I don't want any padding in the container it is in.
code:
return Column(children: [
Container(
padding: EdgeInsets.all(0),
margin: EdgeInsets.all(0),
alignment: Alignment.topLeft,
color: Colors.grey,
width: double.infinity,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: AspectRatio(
aspectRatio: 1 / 1,
child: VpBaseCard(
elevation: 0,
width: double.infinity,
children: [
FaIcon(FontAwesomeIcons.cameraRetro,
size: 100,
color: Colors.white.withOpacity(0.7))
],
active: true,
padding: const EdgeInsets.all(PAD_0),
onPressed: () {},
))),
Expanded(
flex: 1,
child: AspectRatio(
aspectRatio: 1 / 1,
child: VpBaseCard(
inactiveColor: Colors.grey,
width: double.infinity,
children: [
FaIcon(FontAwesomeIcons.imagePolaroid,
size: 100,
color: Colors.white.withOpacity(0.7))
],
active: false,
padding: const EdgeInsets.all(PAD_0),
onPressed: () {},
)))
])),
]);
VpBaseCard:
class VpBaseCard extends StatelessWidget {
VpBaseCard(
{#required this.active,
this.icon,
this.text,
this.width,
this.children,
this.inactiveColor = Colors.white,
this.activeColor,
this.height,
this.expanded = false,
this.iconSize,
this.overflow,
this.elevation = ELEVATION_2,
#required this.onPressed,
#required this.padding});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
HapticFeedback.lightImpact();
onPressed();
},
child: Container(
padding: padding,
height: height,
child: Card(
clipBehavior: Clip.antiAlias,
color: active
? activeColor ??
Theme.of(context).primaryColor.withOpacity(0.7)
: inactiveColor ?? Colors.white,
elevation: active ? elevation : 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Container(
width: width,
height: height,
padding: const EdgeInsets.all(0),
child: Flex(
direction: Axis.vertical,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: children ?? [])))));
}
bool active;
List<Widget> children;
bool expanded;
double width;
double height;
double iconSize;
double elevation;
TextOverflow overflow;
IconData icon;
String text;
VoidCallback onPressed;
EdgeInsetsGeometry padding;
Color inactiveColor;
Color activeColor;
}
Why does the Container seem to have slight padding?
The Card widget within your VpBaseCard has a default margin of EdgeInsets.all(4.0). Try setting that to zero.
https://api.flutter.dev/flutter/material/Card/margin.html