Flutter make container height match_parent - flutter

I have to build the following widget, which will be placed inside a ListView as parent element.
I have a problem with the green rectangle on the left side.
Basically I have structured my widget like that:
-> Card
-> Stack
-> Container for the "right" side (Tire ID, icon, temperature, pressure info)
-> Container for green rectangle,
-> Container with boxed decoration for green circle
-> Text with "5LO"
But this is how it looks like right now:
Basically the Container for the rectangle on the left side is not stretching it's height to full height of the parent stack. How can I do this?
Code:
class TireListItem extends StatelessWidget {
static const _circleSize = 36.0;
const TireListItem({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.zero,
key: Key('cardTire'),
child: Stack(
alignment: AlignmentDirectional.centerStart,
children: [
_TireContentInfoWidget(),
_buildTireIndicationRectangle(), // This should build the rectangle on the left side.
_buildTirePositionCircle(),
_buildTirePositionTextView(context)
],
));
}
Widget _buildTireIndicationRectangle() {
return Container(
width: _marginLeft,
decoration: BoxDecoration(
color: AppColor.green,
shape: BoxShape.rectangle,
borderRadius: BorderRadiusDirectional.horizontal(
start: Radius.circular(Dimens.cardCornerRadius))),
);
}
Container _buildTirePositionCircle() {
return Container(
width: _circleSize,
height: _circleSize,
decoration: BoxDecoration(color: AppColor.green, shape: BoxShape.circle),
);
}
Container _buildTirePositionTextView(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: Dimens.spacingXs),
child: Text(
"2RO",
style:
Theme.of(context).textTheme.button.apply(color: AppColor.white),
));
}
}
If I set a fixed height to the rectangle container, it would basically work out, but I want that the text information area is defining the full height of the widget:
Widget _buildTireIndicationRectangle() {
return Container(
width: _marginLeft,
height: 150,
decoration: BoxDecoration(
color: AppColor.green,
shape: BoxShape.rectangle,
borderRadius: BorderRadiusDirectional.horizontal(
start: Radius.circular(Dimens.cardCornerRadius))),
);
}

You can solve this problem by using IntrinsicHeight class. If you wrapping Stack with InstrinctHeight, Stack's height is fixed by parent's height. Please look IntrinsicHeight document.
https://api.flutter.dev/flutter/widgets/IntrinsicHeight-class.html
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.zero,
key: Key('cardTire'),
child: IntrinsicHeight(child: Stack(
alignment: AlignmentDirectional.centerStart,
children: [
_TireContentInfoWidget(),
_buildTireIndicationRectangle(), // This should build the rectangle on the left side.
_buildTirePositionCircle(),
_buildTirePositionTextView(context)
],
),
),
);
}

Related

how to make blur in flutter

I want to make When I click the sign-up button on the login page, blur is applied to the entire page and I want to show a pop-up window.
When clicking, I changed the filter value by specifying the sigmaX, Y values of the background filter as variables.
However, this uses the stack to place the backgrounddropfilter in front of the entire screen scaffold widget.When this happens, the button cannot be clicked because it goes behind the background filter.
how can I solve it?
Scaffold widgets with blur applied and scaffold widgets without blur
Isn't there a way to make each one and then print it out when the button is pressed?
Widget build(BuildContext context) {
return Stack(children: [
Scaffold(
appBar: AppBar(
...
),
body:ButtonTheme(
minWidth: 100.0,
height: 50.0,
child: ElevatedButton(
)
)
makeblur(a: )
)
);
}
class makeblur extends StatelessWidget {
makeblur({required this.a});
double a;
#override
Widget build(BuildContext context) {
return Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: a, sigmaY: a),
child: Container(
color: Colors.transparent,
),
));
}
}
The child component of backdrop filter is the part that will not be blurred. So you may have to place the button as the child of the backdrop filter
BackdropFilter(
filter: ImageFilter.blur(sigmaX: a, sigmaY: a),
child: Button(),//<-- button that you wish not to blur here.
)
You can use this widget to have the effect, wrap your widget GlassMorphism
class GlassMorphism extends StatelessWidget {
GlassMorphism({
Key? key,
required this.blur,
required this.opacity,
required this.child,
BorderRadius? borderRadius,
}) : _borderRadius = borderRadius ?? BorderRadius.circular(12),
super(key: key);
final double blur;
final double opacity;
final Widget child;
final BorderRadius _borderRadius;
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: _borderRadius,
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: blur,
sigmaY: blur,
),
child: Container(
decoration: BoxDecoration(
color: ColorPallet.glassMorphism.withOpacity(opacity),
borderRadius: _borderRadius,
border: Border.all(
color: ColorPallet.glassMorphism.withOpacity(.2),
),
),
child: child,
),
),
);
}
}

Container color almost transparent in BoxDecoration with a predefined color function

The following code works fine to get the right container color. However, when I want to use the _green function replacing Color(0xff0c9869) in the BoxDecoration widget, the color turns out to be very pale/transparent.
It seems like the same solution, but the result is totally different, anyone knows why?
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
final _green = Color(0xff0c9869);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
Container(
height: 200,
decoration: BoxDecoration(
color: Color(0xff0c9869),
borderRadius: BorderRadius.all(
Radius.circular(35),
),
),
child: Row(
children: [Text('Hi'), Icon(Icons.account_circle)],
),
)
]));
}
}

Drawing Widgets at specific pixel locations for different screen sizes

I'm trying to build a simple Flutter application that displays a full-screen background image and enables the user to drag certain widgets (i.e. a basic circle) from pre-defined start positions (given in pixels) to pre-defined target positions (also given in pixels). The following screenshot from the TouchSurgery app shows a very similar setup to what I'm trying to achieve (green circle = start position, white circle = target position):
My biggest concern at this point are different screen sizes. Let's assume we have an iPhone SE (second generation) with a resolution of 750 x 1334. I can create the following background image with the desired resolution and randomly determine the desired start position to be at coordinates (430, 949) (for simplicity we can disregard the target position):
With the following widget, I can render a circular Container on top of the starting point:
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
var dpr = MediaQuery.of(context).devicePixelRatio;
return Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/iPhoneSE.png"),
fit: BoxFit.fill,
),
),
),
Positioned(
left: 430 / dpr,
top: 949 / dpr,
child: Container(
width: 77.0 / dpr,
height: 77.0 / dpr,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
),
],
),
);
}
}
The resulting image looks like this:
Things start to get tricky when I add an AppBar or a BottomNavigationBar to my application. Both Widgets have a default height of 56 pixels. Given a devicePixelRatio of 2 on the iPhone SE, I need to crop the size of my background image to 750 x 1110 for the overlay to still be accurate (1334 - 2 * 56 (AppBar) - 2 * 56 (BottomNavigationBar)).
Things get even more complicated for other devices such as the iPhone XR, where also the size of the safe area has to be considered. And for Android, there's even more different screen resolutions available.
My question now is the following: instead of creating differently sized background images for 20-30+ different screen sizes - is there a more efficient way in Flutter to draw widgets such as a circular Container at very specific screen locations that works independently of the actual screen size?
You need to get the size of the image container BEFORE positioning your Positioned Widget.
Because as you said, the screen size could change, independently of the image size (e.g. The screen is taller but has a bigger SafeArea, or has an appBar and BottomAppBar. The image could be the same size even if the screen size increased...)
Since your Positioned widget and your image Container are in the same build method, you have to use a LayoutBuilder widget to track the size of your image Container before moving on to building your Positioned widget.
Here's how:
(I've included 2 fully working examples so that you can see that the red circle keeps the same relative position to the background image, even when the image size changes. Your corrected code is the first example).
Example 1
/*
I used these calculated ratios based on your code.
Feel free to use any other way to get these ratios.
The method will be the same.
- The image takes all the available width and height
- The positioned element is postioned :
58.9% from the left of the image container
72% from the top of the image container
- The inner container's:
width is 7.129629629% of the Image Container's width,
height is 4.292084726% of the Image Container's height,
*/
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) { //This is key
return Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/iPhoneSE.png"),
fit: BoxFit.fill,
),
),
),
Positioned(
left: 0.589 * constraints.maxWidth,
top: 0.72 * constraints.maxHeight,
child: Container(
width: 0.07129629629 * constraints.maxWidth,
height: 04292084726 * constraints.maxHeight,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
),
],
),
);
});
}
}
Example 1 image:
Example 2 (with an AppBar and BottomAppBar)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of app"),
),
body: LayoutBuilder(builder: (context, constraints) {
return Column(
children: <Widget>[
Flexible(
fit: FlexFit.loose,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/iPhoneSE.png"),
fit: BoxFit.fill,
),
),
),
Positioned(
left: 0.589 * constraints.maxWidth,
top: 0.72 * constraints.maxHeight,
child: Container(
width: 0.07129629629 * constraints.maxWidth,
height: 0.04292084726 * constraints.maxHeight,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
),
],
),
),
],
);
}),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Text("Home")),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle), title: Text("Profile")),
],
),
);
}
}
Example 2 image:
How about using a Transform.scale widget on your stack and just resizing the whole thing to fit inside whatever constraints the device has?
Something like this:
Transform.scale(
alignment: Alignment.topLeft,
scale: scaleVar,
child: Stack(
children: <Widget>[
Positioned(
top: 0,
left: 0,
child: Image(
image: AssetImage("assets/iPhoneSE.png"),
alignment: Alignment.topLeft,
),
),
Positioned(
left: 430,
top: 949,
child: Container(
width: 77.0,
height: 77.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
),
],
),
)

Flutter - How can I add a widget to the border of a Container?

Assuming that I have an ordinary container. How can I add a widget, for example, a Button to the border of my Container?
Container with a button on border
You can use Badges plugin. for example, in your case you can wrap the container with Badge and modify the position parameter which is a BadgePosition to the exact bottom and right values.
Badge(
position: BadgePosition.bottomRight(bottom: 0,right: 0),//change this to get the right location
badgeContent: YourWidgetAtTheBorder(),
child: YourContainer(),
)
You can use a Stack widget to overlap some widgets, then just create first the container (I used a Card just to simulate the elevation and border effect) and after that add the icon, button, etc, by deault it aligns thewidget in the TopLeft corner, I change it to the centerRight, but if you want more control just wrap the widget in an Align or a Positioned widget to move them where you want
class MyWidget extends StatelessWidget {
final Size size = Size(400, 400);
#override
Widget build(BuildContext context) {
return Stack(alignment: Alignment.centerRight, children: [
Card(
margin: const EdgeInsets.all(24.0), //half the size the icon so it looks like in the middle of the border
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
side: BorderSide(color: Colors.blue, width: 2)
),
color: Colors.grey,
child: SizedBox.fromSize(
size: size, child: Center(child: Text('MyText'))
)
),
Icon(Icons.done, size: 48)
]);
}
}

If I created a widget, how can I set the width or height as screen ratio?

If I created a widget, how can I set the width or height as screen ratio?
class HomeContent extends StatelessWidget{
#override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Container(
child: Image.network("http://a1.att.hudong.com/60/38/01200000194369136323385641912.jpg"),
width: 500,
height: 500,
decoration: BoxDecoration(
color: Colors.yellow,
),
),
);
}
}
You see my upper code, I want the width:Center_height as 1:2, how can I implement?
I mean the Center be carpeted with the screen page, the Container's height : Center's height = 1:2.
instead of directly passing value,
try using MediaQuery class.
Example
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
MediaQuery class will return the height / width of the current device, and you can directly use it accordingly, you can also use it like this,
width: MediaQuery.of(context).size.width / 2,
here, widget will occupy the half width available in current screen.
Use Mediaquery forheight and Width
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
And implement like this
class HomeContent extends StatelessWidget{
#override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Container(
child: Image.network("http://a1.att.hudong.com/60/38/01200000194369136323385641912.jpg"),
width: width,
height: height,
decoration: BoxDecoration(
color: Colors.yellow,
),
),
);
}
}