Responsive Layout with Flutter - flutter

I'm having issue while making the dashboard for my WebApp. I'm trying to make my webApp responsive. But not able to make it. Here is the image with the code for what I tried.
import 'package:flutter/material.dart';
class MyHomeScreen extends StatefulWidget {
const MyHomeScreen({super.key});
#override
State<MyHomeScreen> createState() => _MyHomeScreenState();
}
class _MyHomeScreenState extends State<MyHomeScreen> {
List<Widget> customWidgetList = [
Container(
height: 100,
width: 200,
color: Colors.grey.shade200,
),
Container(
height: 300,
width: 200,
color: Colors.grey.shade200,
),
Container(
height: 100,
width: 200,
color: Colors.grey.shade200,
),
Container(
height: 100,
width: 200,
color: Colors.grey.shade200,
),
Container(
height: 200,
width: 200,
color: Colors.grey.shade200,
),
Container(
height: 100,
width: 200,
color: Colors.grey.shade200,
),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Responsiveness')),
body: Wrap(
spacing: 2.0,
runSpacing: 2.0,
clipBehavior: Clip.antiAlias,
children: customWidgetList,
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
);
}
}
Result of above code :
Where as I want to fill all the empty spaces. Here is the image of what I want to do it.

Simple answer is to add direction: Axis.vertical to Wrap widget.
The correct answer is to create your own LayoutBuilder and calculate for each Container its correct position.
The easiest is to use https://pub.dev/packages/flutter_staggered_grid_view

Related

I cant find anything wrong. why cant I add 2 containers in the Column

home: Scaffold(
backgroundColor: Colors.teal,
body: Column(
children: [
Container(
color: Colors.red,
width: 100,
height: 100,
)
Container(
color: Colors.blue,
width: 100,
height: 100,
)
You have forgot to include , end of the Container
Scaffold(
backgroundColor: Colors.teal,
body: Column(
children: [
Container(
color: Colors.red,
width: 100,
height: 100,
), //this
Container(
color: Colors.blue,
width: 100,
height: 100,
)
],
),
);
If you are using vs-code, try Error Lens extension
Since you have used home:Scaffold I believe you have a material app. If you had included const before the return Material app it will throw an error here.. also as #Yeasin Sheikh mentioned you have missed a , between Container widgets
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
Container(
color: Colors.red,
width: 100,
height: 100,
),
Container(
color: Colors.blue,
width: 100,
height: 100,
)
],
),
));
}
}

How to create a sticky header from the container that is in the middle

import 'package:flutter/material.dart';
void main() {
runApp(Test());
}
class Test extends StatelessWidget {
#override
Widget build(context) {
return SingleChildScrollView(
child: Column(children: [
Container(
height: 100,
color: Colors.white,
child: const Text("Titleeeee"),
),
Container(
height: 300,
color: Colors.blue,
child: const Text("STICKEEEYYYY"),
),
Container(
height: 100,
color: Colors.orange,
child: const Text("CCCCCCC"),
),
Container(
height: 100,
color: Colors.orange,
child: const Text("CCCCCCC"),
),
]),
);
}
}
I have this Column widget. Trying to make the second container - Text('STICKEEEY') the sticky header. I've been trying to use the sticky_header package.
Container(
child: SingleChildScrollView(
child: Column(
children: [
Container(
height: 100,
color: Colors.white,
child: const Text("Titleeeee"),
),
StickyHeader(
header: Container(
height: 300,
color: Colors.blue,
child: const Text("STICKEEEYYYY"),
),
content: Column(children: [
Container(
height: 100,
color: Colors.orange,
child: const Text("CCCCCCC"),
),
Container(
height: 100,
color: Colors.orange,
child: const Text("CCCCCCC"),
),
]),
),
],
),
),
)
However, this does not hold the second container at the top. It bypasses when it scrolls down. How can I make it stick to the top in this case?
Slives maybe are what you are looking for.
Doc: https://docs.flutter.dev/development/ui/advanced/slivers
You can use SilverAppBar
Doc : https://api.flutter.dev/flutter/material/SliverAppBar-class.html

Flutter: how to use ListView with expanded inside the nested column

#override
Widget build(BuildContext context) {
return Column(
children: [
Text(
"Scrolling Viewww :( ",
style: TextStyle(fontSize: 25),
),
Column(
children: [
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
Column(children: [
ListView( <------------------ **Making this Expanded**
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: [
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
],
),
]),
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
],
)
],
);
I have tried to implement Expanded to resolved this. However, since it is nested twice, it was quite tricky. Only way that I could have done is just to set the Container() widget with given height.
But, in my real Column() widget, I have an AnimatedContainer that changes with its height. So, I want to find a way that I can do this with Expanded or Flexible.
I'd tried million different combinations. Nothing seems to work. How can I make the ListView that is inside the nested Column expandable?
Did you want to fix two item over ListView?
I implemented your request.
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return SafeArea(
child: Container(
child: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 40,
maxHeight: 40,
child: Container(
color: Colors.white,
child: Text(
"Scrolling Viewww :( ",
style: TextStyle(fontSize: 25),
),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
height: 100,
width: 100,
color: Colors.blue,
child: Text('box1'),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
height: 100,
width: 100,
color: Colors.blue,
child: Text('box2'),
),
),
),
];
},
body: Builder(
builder: (BuildContext context) {
final innerScrollController = PrimaryScrollController.of(context);
return SingleChildScrollView(
controller: innerScrollController,
child: Column(
children: [
ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: [
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
Container(
height: 100,
width: 100,
color: Colors.red,
),
SizedBox(
height: 10,
),
],
),
Container(
height: 100,
width: 100,
color: Colors.blue,
),
SizedBox(
height: 10,
),
],
),
);
},
),
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
#required this.minHeight,
#required this.maxHeight,
#required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
#override
double get minExtent => minHeight;
#override
double get maxExtent => math.max(maxHeight, minHeight);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
To avoid the bottom overflow, try wrapping a SingleChildScrollView around the first Column. Additionally you can play around with the mainAxisSize property of the different Columns.

Flutter OverflowBox is behind the next widget in a column

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:

How can I add a header card to a flutter card

I am trying to add a header card which will be displayed on the upper-left edge of a flutter card, so far I haven't been able to achieve that. This is an example of what I want
Being new to flutter, I didn't know there was a Stack widget. The solution is to stack two cards wrapped in Positioned widgets.
class SummaryCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 0,
top: 40,
height: 200,
width: 350,
child: Card(
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
Positioned(
left: 20,
top: 0,
height: 100,
width: 100,
child: Card(
color: Colors.green,
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
],
);
}
}
You need to wrap header card with Align Widget.
Here is a full code:
class Cards extends StatefulWidget {
#override
_CardsState createState() => _CardsState();
}
class _CardsState extends State<Cards> {
#override
Widget build(BuildContext context) {
return Container(
height: 200,
width: 200,
child: Card(
elevation: 20,
child: Align(
alignment: Alignment.topLeft,
child: Container(
width:100,
height: 60,
child: Card(
elevation: 10,
child: Text("header"),
),
),
),
),
);
}
}
Containers are just for height and width control.
And here is a screenshot: