Im building a screen where a widget is supposed to look like a Tweet. Im trying to implement the vertical bars seen under profile pictures with the following:
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
VerticalDivider(
color: Colors.red,
thickness: 10,
width: 20,
),
//make a widget that looks like twitter composing tweet
CircleAvatar(
radius: 20,
backgroundImage: NetworkImage(user.imageUrls[0]),
),
//add a gray line that runs down the middle of the screen
VerticalDivider(
color: Colors.red,
thickness: 10,
width: 200,
),
],
),
),
Which looks like this:
As you can see, the dividers are invisible. Wrapping the divider with a specified height makes it look like this:
It is now visible, but obviously expands outside of the original size of the widget. Is there any way to pass the size of the parent into the VerticalDivider so i knows how much space it has to work with?
Thanks!
You can wrap your Row with the IntrinsicHeight widget. It will set the rows height based on its tallest child (here the Container with height = 200). Of course in your example you don't know the tallest child's size before layout, I used the container simply to give you an example. IntrinsicHeight is relatively expensive to use but the right choice for such use cases (see its docs).
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: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return IntrinsicHeight(
child: Row(
children: [
Container(
color: Colors.grey,
child: Column(
children: [
SizedBox(
child: VerticalDivider(
color: Colors.red,
thickness: 10,
width: 20,
),
height: 20,
),
Container(height: 40, width: 40, color: Colors.blue),
Expanded(
child: VerticalDivider(
color: Colors.red,
thickness: 10,
width: 20,
),
),
],
),
),
Container(
height: 200,
width: 200,
color: Colors.white,
)
],
),
);
}
}
Related
This is my first question and I'm new in Flutter. I searched a lot but I did not find any suitable answers.
Flutter: I need to set my box height flexible to fit any size of screen. I also need to fit my last box to the right side of screen to fit any screen. I also mentioned my problem in the image of screen. Kindly help. I'm adding my code here.
Output and requirement of my code
void main() {
runApp(const Challange2());
}
class Challange2 extends StatelessWidget {
const Challange2({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: SafeArea(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 850.0,
width: 100.0,
color: Colors.amberAccent,
child: Text(
'This box height should be flexible according to screen size',
style: TextStyle(color: Colors.black, fontSize: 25),
),
),
const SizedBox(
width: 65,
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 100.0,
width: 100.0,
color: Colors.deepPurpleAccent,
child: Text(
'Text2',
style: TextStyle(color: Colors.white, fontSize: 25),
),
),
Container(
height: 100.0,
width: 100.0,
color: Colors.deepOrangeAccent,
//Flexible(
child: Text(
'Text3',
style: TextStyle(color: Colors.white, fontSize: 25),
),
),
//),
],
),
const SizedBox(
width: 65,
),
Container(
height: 850.0,
width: 100.0,
color: Colors.blue,
child: Text(
'This box need to be right alignment and height should be flexible according to screen size',
style: TextStyle(color: Colors.black, fontSize: 25),
),
// child: const Align(
// alignment: Alignment.topCenter,
),
],
),
),
),
//),
//return Container();
);
}
}
To adapt to screen height, you can set height of containers to double.infinity,
To keep rigth container aligned to the right, use expanded in the center row child, in order to make this widget grow or shrink as needed.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(children: [
Container(
width: 100,
height: double.infinity,
color: Colors.red,
child: Text(
'This box height should be flexible according to screen size'),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 50,
height: 50,
color: Colors.green,
),
Container(
width: 50,
height: 50,
color: Colors.yellow,
),
]),
),
Container(width: 100,
height: double.infinity,
color: Colors.blue, child:Text("Right Panel"),),
]),
);
}
}
LayoutBuilder() Provides a way to get the actual screen size dynamically and allows you to calculate relative sizes: Youtube - Flutter: LayoutBuidler
Generally when using Rows and Columns you can use Expanded widgets to have relative instead of absolute sizes:
Row(
children: [
Expanded(flex: 1, child: Container()), // This will take up 1 third of the screen
Expanded(flex: 2, child: Container()), // This will take up 2 thirds of the screen
]
),
Expanded(flex: 1, child: Container()),
Expanded(flex: 1, child: Container()),
Help me, any idea how to remove the space between yellow and green Container?
It's caused by the Container have additional height after transform translate.
I need CustomSrollView with SliverAppBar and a child below it.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
body: Example(),
),
);
}
}
class Example extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CustomScrollView(slivers: [
SliverSafeArea(
top: false,
sliver: SliverAppBar(
backgroundColor: Colors.black.withOpacity(0.2),
floating: true,
toolbarHeight: 0,
bottom: const PreferredSize(
preferredSize: Size.fromHeight(30), child: Text("AppBar")),
),
),
SliverToBoxAdapter(
child: Transform.translate(
offset: const Offset(0.0, -30.0),
child: Container(height: 500, color: Colors.yellow),
),
),
SliverToBoxAdapter(
child: Align(child: Container(height: 500, color: Colors.green))),
]);
}
}
Ok, you want to move the yellow container, but you don't want to take translate spaces the space. I don't know what design you are doing, I may just reduce the height in this case. Or use padding in extra spaces.
According to the question, we can use stack like.
SliverToBoxAdapter(
child: Container(
color: Colors.amber,
height: 500 + 500,
child: Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 500,
color: Colors.green,
),
),
Positioned(
bottom: 500 - 30,
child: Transform.translate(
offset: const Offset(0.0, -30.0),
child: Container(
height: 500,
color: Colors.yellow,
),
),
),
],
),
),
),
But in this case we are overlapping with green container.
We can
reduce the size,
use stack, will overlap with green container
im trying to set 2 containers on top of each other. What I want is to showing a star and when user pressed the star I wanna open 5 star so he can vote . Im not really sure if im thinking the correct way . But fr that I wanna create one container and in another container directly above this stars container displaying all other buttons how's just buttons to clock normally . I hope that you understand what I trying to do. So when im putting the star container also in the same container they buttons when opening all stars the whole container will move isn't?
So heres im trying to do.
class VideoPage extends StatelessWidget {
static const route = '/Video';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
height: 100,
color: Colors.yellow[300],
),
Expanded(
child: Row(
children: [
Expanded(
child: Container(color: Colors.green[300]),
),
Container(
width: 100,
color: Colors.orange[300],
),
Container(
width: 100,
color: Colors.red[300],
),
],
),
),
Container(
height: 80,
color: Colors.blue[300],
),
],
),
);
}
}
This look like that:
And I want that the orange one is directly under the red one so there will be first one star and on pressing it open 5 stars . Is this possible what im trying ? If so please help . If not please help haha
What you need to use is the Stack Widget:
Stack(
children: <Widget>[
BottomWidget(),
MiddleWidget(),
TopWidget(),
],
),
The last widget of the children is the top layer, structure descending.
more info: https://medium.com/flutter-community/a-deep-dive-into-stack-in-flutter-3264619b3a77
EDIT:
In your case if you want the orange one underneath, you have to do some changes within your structure and split it from your Row()
Example
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 Scaffold(
body: Column(
children: [
Container(
height: 100,
color: Colors.yellow[300],
),
Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width *1,
height: 200,
color: Colors.orange,
),
Container(
height:200,
child: Row(
children: [
Expanded(
child: Container(color: Colors.green[300]),
),
Container(
width: 100,
color: Colors.red.withOpacity(0.5),
),
],
)),
],
),
Container(
height: 80,
color: Colors.blue[300],
),
],
),
);
}
}
The following flutter example results in the green box and text actually exceeding the constraints of the parent container. Why does this happen in this case? Basically the column is exceeding its incoming parent constrained height of 400, and seems to be using the top parent container height when making decisions on where to layout its children. Also the black border is not visible?
I have also tried using sizedbox, constrainedbox and the result is the same.
This is purely to understand the reason why this happens in more detail.
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 Container(
width: double.infinity,
height: double.infinity,
color: Colors.red,
child: Container(
height: 400,
decoration: BoxDecoration(border: Border.all(color: Colors.black)),
constraints: BoxConstraints(maxHeight: 400),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 50,
width: 50,
child: Container(
color: Colors.green,
)
),
Text("Test")
]
)
)
);
}
}
I know it's over a year since this issue was raised, but I recently ran into a very similar issue, and (by experimenting) I found a solution
My problem can be better demonstrated by having the Column contain multiple Text entries that are multiple lines long, and the overflow marker appears, but the text continues on the screen
The actual solution seems quite simple but not immediately obvious... wrap the Text entries in a Flexible!
SizedBox(
height: 131,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
text1,
),
Flexible(
child: Text(
text2,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 10,
),
),
),
],
),
);
I'm working on a Flutter project and I am trying to use the OverflowBox widget.
I have a list of widgets in a Column, one of them, in the middle is supposed to overflow the others based on some events by the user.
Here is a simplified version of my code.
The red Container needs to display the green Container that overflows it at the top and the bottom.
But as you can see on the image, the green Container is only visible above the previous Container (the blue one) but not on the next one (the black Container). It looks like it is behind.
class MyScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 100,
width: 100,
color: Colors.blue,
),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Center(
child: OverflowBox(
maxHeight: 150,
child: Container(
color: Colors.green,
height: 150,
width: 50,
),
),
),
),
Container(
height: 100,
width: 100,
color: Colors.black,
)
],
);
}
}
How can I get my green Container to be above the black one too ?
EDIT: For functionality purposes, I need the green Container to be a child/be created by the red Container (and not by the list where I could use a Stack widget). I need the logic to be inside the red and green ones.
It still uses Stack, but Green Container is still part of Red Container.
And it might be difficult to calculate margin if Container has dynamic height.
class MyScreen extends StatelessWidget {
const MyScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
height: 100,
width: 100,
color: Colors.blue,
),
Container(
margin: const EdgeInsets.only(top: 200),
height: 100,
width: 100,
color: Colors.black,
),
Container(
margin: const EdgeInsets.only(top: 100),
height: 100,
width: 100,
color: Colors.red,
child: Center(
child: OverflowBox(
maxHeight: 150,
child: Container(
height: 150,
width: 50,
color: Colors.green,
),
),
),
),
],
),
);
}
}
Use of overlay, maybe solve your problem.
OverlayState? overlayState = Overlay.of(context);
I tried your code snipped and failed to getting the design that you particularly wishing to achieve.
I have anther way to get such type of design. Which ia using Stacl() widget
Here is an complete example code snippet
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: MyScreen(),
),
),
);
}
}
class MyScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: MediaQuery.of(context).size.height/3,
width: MediaQuery.of(context).size.width,
color: Colors.blue,
),
Container(
height: MediaQuery.of(context).size.height/3,
width: MediaQuery.of(context).size.width,
color: Colors.red,
),
Container(
height: MediaQuery.of(context).size.height/3,
width: MediaQuery.of(context).size.width,
color: Colors.black,
)
],
),
Positioned(
// to set a specific position of your widget use Positioned inside a Stack() widget
/*
bottom: 50,
top: MediaQuery.of(context).size.height/3,
left: 100,
right: 100,
*/
child: OverflowBox(
child: Container(
color: Colors.green,
height: MediaQuery.of(context).size.height/2,
width: 100,
),
),
),
],
);
}
}
Output: