Hi I created 3 containers but when I use a different device it obviously doesn't scale properly. How can I set as a Container as a specific size to any device. This is my code.
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Welcome to my app"),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(padding: EdgeInsets.fromLTRB(450.0, 0.0, 100.0, 0.0)),
Container(
height: MediaQuery.of(context).size.height - 100,
color: Colors.grey[600],
),
Container(
color: Colors.amber,
height: MediaQuery.of(context).size.height - 100,
),
Container(
color: Colors.black,
height: MediaQuery.of(context).size.height - 100,
),
],
),
),
);
}
}
Use MediaQuery widget:-
Container(
color: Colors.amber,
height: MediaQuery.of(context).size.height - 100, // set this calculation as per your requirement
),
Container(
color: Colors.teal,
height: MediaQuery.of(context).size.height - 200, // set this calculation as per your requirement
),
You can use Expanded Widgets and give it flex according to your requirements.
also you can use this flutter plugin to provide width and height in terms of %.
https://pub.dev/packages/responsive_flutter
// Example 20% of screen's width
ResponsiveFlutter.of(context).wp(20)
// Example 20% of screen's height
ResponsiveFlutter.of(context).hp(20)
Related
This is my code,
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Example',
home: Scaffold(
backgroundColor: Colors.green.shade200,
body: Column(
children: [
ClipPath(
clipBehavior: Clip.antiAlias,
clipper: MyCustomClipper(),
child: Container(
width: 600,
height: 300,
color: Colors.green.shade300,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.shopping_cart_outlined, color: Colors.black87, size: 30,),
Text('Example', style: TextStyle(fontSize: 22, color: Colors.black87,)),
],
),
),
),
Container(
height: 360,
width: 300,
color: Colors.white,
),
],
),
),
);
}
}
this is my clipper class, its just a basic design that we see on every other flutter app,
// clipper class
class MyCustomClipper extends CustomClipper <Path> {
#override
Path getClip(Size size) {
Path path = Path();
path.lineTo(0, size.height / 2 );
path.quadraticBezierTo(size.width / 2 , size.height, size.width, size.height / 2 );
path.lineTo( size.width , 0);
return path ;
}
#override
bool shouldReclip(covariant CustomClipper <Path> oldClipper ) {
return true ;
}
}
Current Situation
i really don't know how we can achieve such things
clip-path does not have any padding and margin by default
tried stack but no luck ?
used alignment property no luck
i read on other thread that clipping should be done separately not on the whole widget what does that mean ?
i want the height and width to adjust with each phone so the picture will fit right in every phone.
i am just writing more so the post would get submitted the qustion is simple
//
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.red,
appBar: (AppBar(
title: Center(
child: Text('lord thunder'),
),
backgroundColor: Colors.white60,
)),
body: Center(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: FittedBox(
child: Image.asset('images/images.jpg'),
fit: BoxFit.fill,
),
),
),
),
),
);
``
i was trying to make the picture fit the body perfectly on each phone.
You can use BoxFit.cover propertry inside DecorationImage
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/images.jpg"),
fit: BoxFit.cover
)
),
),
I'm quite seeing the effect of MainAxisSize but I don't understand its purpose. Please explain like I'm 5. Thank you.
For further reference:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Color(0xffEDE7F6),
body: SafeArea(
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Container(
height: 100,
width: 100,
color: Color(0xff9575CD),
child: Text('Container 1'),
),
Container(
height: 100,
width: 100,
color: Colors.black45,
child: Text('Container 2'),
),
Container(
height: 100,
width: 100,
color: Colors.black12,
child: Text('Container 3'),
),
]),
),
),
);
}
}
Output on emulator:
Let's say you have a container of height 400 wrapped around a column containing 3 rows of height 100 (either defined by height or intrinsic by what is in there), that leaves you 100pt of height unused.
MainAxisSize.max says, distribute all space between the column's items, so create spaces of 50 between the rows.
MainAxisSize.min says, squeeze the rows together and leave unused space (100) at the end (or beginning or both ends depending on alignment)
Clipping allows me to draw only the part which I want to show. How do I remove the extra part which is not drawn but still takes up space?
The code
import 'package:flutter/material.dart';
class ClipTut extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: <Widget>[
ClipRect(
clipper: CustomRect(),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 4, color: Colors.black),
color: Colors.blue,
),
width: 200.0,
height: 200.0,
),
),
Container(
height: 200,
width: 100,
decoration: BoxDecoration(
border: Border.all(width: 4, color: Colors.black),
color: Colors.green,
),
)
],
),
),
);
}
}
class CustomRect extends CustomClipper<Rect> {
#override
Rect getClip(Size size) => Rect.fromLTRB(0, 0.0, size.width/2, size.height);
#override
bool shouldReclip(CustomRect oldClipper) => true;
}
My Solution
I had a similar problem recently (I needed to clip the image in half) and found this sample code on the flutter api site (use the other alignment points to change slicing behaviors) - no extra space left over:
ClipRect(
child: Align(
alignment: Alignment.topCenter,
heightFactor: 0.5,
child: Image.network(userAvatarUrl),
),
)
My base widget is a Column. The first element is a Container which has a BoxShadow. The second element is a ListView which builds several Card, depending on the context. If the scroll is 0 the shadow gets displayed. However when start scrolling, the card is "over" the shadow (higher z-index) and hides it.
unscrolled
scrolled
The shadow should stay always on top, over the Cards. How is this done?
EDIT
if you don't want container shadow to disappear on scroll remove the ScrollNotification and NotificationListener
There is a widget for that 😉
You can use ScrollNotification with NotificationListener. Try this;
Happy coding! 🤓
class TestPage extends StatefulWidget {
const TestPage({Key key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
double blurRadius = 10.0;
double spreadRadius = 1.0;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey,
title: Text('Title'),
),
body: Container(
width: Get.width,
height: Get.height,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0).copyWith(
top: 62.0,
),
child: NotificationListener<ScrollNotification>(
// ignore: missing_return
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
setState(() {
blurRadius = 0.0;
spreadRadius = 0.0;
});
} else if (scrollNotification is ScrollEndNotification) {
setState(() {
blurRadius = 10.0;
spreadRadius = 1.0;
});
}
},
child: ListView.builder(
// controller: _controller,
itemCount: 10,
itemBuilder: (context, index) {
return Card(
child: Container(
width: Get.width * .8,
height: 100.0,
child: Center(
child: Text('child # index : $index'),
)),
);
},
),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
width: Get.width,
height: 60.0,
margin: EdgeInsets.only(),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: blurRadius,
spreadRadius: spreadRadius,
),
],
),
child: Center(
child: Text('TOP CONTAINER'),
),
),
),
],
),
),
);
}
}
According to your question, here is the concept of what is going wrong here.
The 1st child of Column is a Container with shadow. Shadow renders outside of the defined size. If you don't provide any spaces after this Container we won't be able to see the shadow. This space can be done by Container margin , SizedBox or wrapping our list with Padding. But now our main question is how we get shadow while index=0. I believe it is coming from ListChildren`. They contain upper spaces, that's why we can see only the 1st time.
On Ui render priority starts from bottom to Top.
How to solve this problem:
We can provide space at the bottom of our container or assign margin(not padding), or use a SizedBox after the container providing the same amount of height as shadow.
providing bottom margin on the container.
adding a SizedBox with height of shadow.
wrapping our list with Padding and providing top:.
In this image,
our shadow: white, background:amber.
Demo code:
import 'package:flutter/material.dart';
class ColumnWithContainerShadow extends StatelessWidget {
const ColumnWithContainerShadow({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: Column(
children: [
Container(
height: 50,
width: double.infinity,
////* we dont need margin if we have padding on ListView
// margin: EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
color: Colors.green,
boxShadow: [
BoxShadow(
offset: Offset(0, 12),
color: Colors.white,
)
],
),
child: Center(child: Text("Container A")),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 12),
child: ListView(
children: [
...List.generate(
333,
(index) => Container(
/// enable this margine and remove other spaces to see 1st child shadow.(shadow depend on children position)
// margin: EdgeInsets.only(top: 12),
height: 60,
color: Colors.deepPurple,
child: Text("$index"),
),
)
],
),
),
),
Container(
height: 50,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.green,
boxShadow: [
BoxShadow(
offset: Offset(0, 12),
color: Colors.white,
)
],
),
child: Text("Bottom Container"),
),
// Comment to close shadow
SizedBox(
height: 20,
)
],
),
);
}
}
Wrap this upper box in Material widget and provide an elevation.