How to put two containers on the same screen without page scrolling? - flutter

I have a search page. I display 2 containers with information on the search page. But I ran into a problem, my bottom station container goes off the screen and I need to scroll the page to see the information. How can I put 2 containers on the screen and not have to scroll the page so that 2 containers fit on the same screen?
1
Widget _addresses(Size size, StationCubit stationCubit) => ConstrainedBox(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height / 2,
),
child: SizedBox(
width: size.width,
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
child: Container(
padding: const EdgeInsets.only(left: 20, top: 17),
decoration: BoxDecoration(
color: constants.Colors.greyXDark.withOpacity(0.8),
borderRadius: BorderRadius.circular(24),
),
child: SingleChildScrollView(
controller: _addressesController,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Addresses',
style: constants.Styles.smallBookTextStyleWhite,
),
const SizedBox(height: 25),
2
Widget _station(Size size, StationCubit stationCubit) => ConstrainedBox(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height / 2,
),
child: SizedBox(
width: size.width,
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
child: Container(
padding: const EdgeInsets.only(left: 20, top: 17),
decoration: BoxDecoration(
color: constants.Colors.greyXDark.withOpacity(0.8),
borderRadius: BorderRadius.circular(24),
),
child: SingleChildScrollView(
controller: _stationController,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Station',
style: constants.Styles.smallBookTextStyleWhite,
),

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(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
Expanded(
child: Container(
color: Colors.deepPurple,
child: ListView.builder(itemBuilder: (c, i) {
return Text("Test $i");
})),
),
Expanded(
child: Container(
color: Colors.deepOrange,
child: ListView.builder(itemBuilder: (c, i) {
return Text("Test $i");
})),
),
],
));
}
}

Try placing both containers in column and wrap both container with flexible/expanded to expand containers in full screen.
Example code:
column(
children: [
Expanded(
child: Container(child: Text("Container 1")
),
Expanded(
child: Container(child: Text("Container 2")
)
]
)

Use 2 Expanded container in single column
column( children: [ Expanded( child: Container(child: Text("Container 1") ), Expanded( child: Container(child: Text("Container 2") ) ] ).

Abdul Rahman Panhyar your answer is right but Max need to show data came from any API so there is a chance of bulk data and just wrapping the container with expanded will disrupt the UI. so what is suggest you can divide your screen in two parts then in each part you can use Listview builder so it will be inner scrollable.

Related

Convert dart code into html/JS web format

Is there any way to convert pure Flutter/Dart code into Html and JS?
My aim is to a basic webpage but from a widget I have created in Flutter. I have read that Dart is compiled behind with JS .
Just wondering if I would be able to see the code behind a page created in flutter, like this one:
import 'package:flutter/material.dart';
class CardWebQR extends class name extends StatelessWidget {
const name({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("QR Code"),
),
body: Column(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.2,
width: MediaQuery.of(context).size.width * 0.76,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
elevation: 10,
margin: const EdgeInsets.all(20),
child: Column(
children: [
Text('hello'),
const SizedBox(height: 10),
Text('bye'),
const SizedBox(height: 10),
CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(url),
),
],
)),
),
),
],
),
);
}
}

SingleChildScrollView rendering overflow when viewport greater than maxwidth

I'm trying to set web content to have a maximum width (the orange in the image), and always fill the available height, which I've achieved.
However when the window is wider than the maximum content width, and the window height is less than the height of the content, header, and footer combined. I'm getting a rendering overflow.
When what I'm after is for content to hold it's height, and the scroll to enable.
Note: the problem seems to go way if each text is only 1 line worth.
I've tried using CustomeScrollView with a SliverFillRemaining, but I get the same problem.
Any assistance would be greatly appreciated.
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 const MaterialApp(
title: 'Scrollable Layout',
home: ScrollableLayout(),
);
}
}
class ContentWidthContainer extends StatelessWidget {
final Widget child;
const ContentWidthContainer({Key? key, required this.child})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.grey,
child: Align(
alignment: Alignment.topCenter,
child: Container(
color: Colors.orange,
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 960,
),
padding: const EdgeInsets.symmetric(horizontal: 75),
child: child),
),
);
}
}
class ScrollableLayout extends StatelessWidget {
const ScrollableLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Header: Fixed Height')),
),
Expanded(
child: ContentWidthContainer(
child: Container(
color: Colors.white,
child: Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
)),
),
),
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Footer: Fixed Height')),
),
],
),
),
),
);
},
),
);
}
}
If the height of the header and footer is 200 each, then the height of the middle content should be less than 400.
height: MediaQuery.of(context).size.height - 400
Therefore change your code to
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints)
{
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Header: Fixed Height')),
),
Expanded(
child: ContentWidthContainer(
child: Container(
height: MediaQuery.of(context).size.height - 400,
color: Colors.white,
child: Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
)),
),
),
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Footer: Fixed Height')),
),
],
),
),
),
);
},
),
);
}
On changing it to use a Column, with just 2 children, and the alignment set to SpaceBetween, the overflow problem disappears when you make the window width but shorter than the content.
class ScrollableSpaceBetweenLayout extends StatelessWidget {
const ScrollableSpaceBetweenLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
color: Colors.black12, // the background / sides
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
color: Colors.indigo,
height: 200,
child: const Align(
alignment: Alignment.center,
child: Text('Header: Fixed Height'))),
Container(
color: Colors.orange,
constraints: BoxConstraints(
maxWidth: 960,
minHeight: max(viewportConstraints.maxHeight - 400, 0),
),
padding: const EdgeInsets.symmetric(horizontal: 75),
child: Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
),
Container(
child: const Text('spacer'),
height: 1,
color: Colors.red)
],
)),
),
Container(
color: Colors.indigo,
height: 200,
child: const Align(
alignment: Alignment.center,
child: Text('Footer: Fixed Height'))),
],
),
),
);
},
),
);
}
}

Achieving this layout in flutter

I am trying to achieve something like this in flutter. I have a horizontal scrollable which has these rounded containers. I want the width of these containers to shrink if the elements in the scrollable is more than 3 and it should expand as per the image if the elements are less than 2. What i want is exactly like this image, i have been reading about flexible widget but when i wrap it inside a scrollable row it gives layout specific issues. Any workaround to achieve this?
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SingleChildScrollView(
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
child: Row(
children: [
...List.generate(
9,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.green,
),
height: 100,
width: 100,
),
),
)
],
)),
SizedBox(
height: 20,
),
Row(
children: [
...List.generate(
2,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 180,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20))),
))
],
),
SizedBox(
height: 20,
),
Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 350,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20))),
),
],
)
],
),
),
);
}
The above build method produces the following result.(The values here are hardcoded and is just for demonstration). The list values are going to be dynamic and the desired result should be like the one in the video. How do i proceed with this?
https://streamable.com/w142je
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(debugShowCheckedModeBanner: false, home: MyHomePage());
}
}
class MyHomePage extends StatefulWidget {
final String hintText = 'hing';
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
#override
Widget build(BuildContext context) {
var list1 = List.filled(2, '2');
var list2 = List.filled(4, '4');
var list3 = List.filled(1, '1');
return SafeArea(
child: Scaffold(
body: Column(
children: [
_getList(context, list1),
_getList(context, list2),
_getList(context, list3),
],
),
),
);
}
Widget _getList(BuildContext context, List<String> list) {
bool ownSize = list.length == 2;
if (ownSize) {
return SingleChildScrollView(
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
child: Row(
children: list.map((t) => rowItem(t, 250)).toList(),
),
);
} else {
return Row(
children: list
.map(
(t) => Expanded(child: rowItem(t)),
)
.toList(),
);
}
}
Widget rowItem(String text, [double? width]) {
return Container(
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.green,
),
height: 100,
width: width,
alignment: Alignment.center,
child: Text(text),
);
}
}

Flutter showing hasSize error when wrap container in column

I am getting an error when I wrap my container in the column widget. I need 2 containers in a column but when I wrap it in column widget it's showing this error
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
Showing this in Column line error
Here is my code
class _PlaceListState extends State<PlaceList> {
final List _places = [
{'name': 'Hunza', 'where': 'Gilgit Baltistan'},
{'name': 'Skardu' ,'where': 'Gilgit Baltistan'},
{'name': 'Murree', 'where': 'Gilgit Baltistan'},
];
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(
margin: EdgeInsets.only(left: 40),
width: MediaQuery.of(context).size.width * 0.5,
child: ListView.builder(
itemCount: _places.length,
itemBuilder: (ctx, int index) {
return Container(
padding: EdgeInsets.only(top: 50),
child: Column(
children: <Widget>[
Text(_places[index]['name'], style: TextStyle(fontSize: 20),),
Container(
padding: EdgeInsets.only(top: 20),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Card(
elevation: 40.0,
child: Container(
width: 200,
child: Image(image: AssetImage('assets/images/500place.jpg')),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 7),
child: Row(
children: <Widget>[
Icon(Icons.favorite_border, size: 20),
Spacer(),
Text(
_places[index]['where'],
),
],
)
),
],
),
);
}),
)
],);
}
}
The screen output i use Navigation rale so that's why I set the width and its working fine without Column widget
You can copy paste run full code below
Step 1: Provide height when use PlaceList() , you can use Expanded(child: PlaceList())
Step 2: add shrinkWrap: true for ListView
Step 3: Use Expaneded flex to provide height for Container() 1 and 2
Column(
children: <Widget>[
Expanded(
flex: 3,
...
Expanded(
flex: 1,
child: Center(child: Container(child: Text("Second Container"))))
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: PlaceList()),
],
),
),
);
}
}
class PlaceList extends StatefulWidget {
#override
_PlaceListState createState() => _PlaceListState();
}
class _PlaceListState extends State<PlaceList> {
final List _places = [
{'name': 'Hunza', 'where': 'Gilgit Baltistan'},
{'name': 'Skardu', 'where': 'Gilgit Baltistan'},
{'name': 'Murree', 'where': 'Gilgit Baltistan'},
{'name': 'abc', 'where': 'def'},
];
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
margin: EdgeInsets.only(left: 40),
width: MediaQuery.of(context).size.width * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: _places.length,
itemBuilder: (ctx, int index) {
return Container(
padding: EdgeInsets.only(top: 50),
child: Column(
children: <Widget>[
Text(
_places[index]['name'],
style: TextStyle(fontSize: 20),
),
Container(
padding: EdgeInsets.only(top: 20),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Card(
elevation: 40.0,
child: Container(
width: 200,
child: Image(
image: AssetImage(
'assets/images/500place.jpg')),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 7),
child: Row(
children: <Widget>[
Icon(Icons.favorite_border, size: 20),
Spacer(),
Text(
_places[index]['where'],
),
],
)),
],
),
);
}),
),
),
Expanded(
flex: 1,
child: Center(child: Container(child: Text("Second Container"))))
],
);
}
}
try adding height: // define height in double to your container
Add the shrinkWrap property to your ListView as seen below:
child: ListView.builder(
itemCount: _places.length,
shrinkWrap: true,
itemBuilder: (ctx, int index) {
return Container(...
Setting the shrinkWrap to true would result in the list wrapping its content and be as big as its children permits
You could also add a height to your Container
return Container(
height: 90,
...
)

Place a CircularProgressIndicator inside RaisedButton mantaining size

I want to place a CircularProgressIndicator inside a RaisedButton, but when I do it, the CircularProgressIndicator doesn't fit the button and sticks out of it.
I want to shrink the CircularProgressIndicator, so that it fits inside the RaisedButton, I know I can do it using a SizedBox but I want it to be automatic, not that I give it the size that I want. I tried FittedBox but all its options make no difference at all.
this is my button's code:
RaisedButton(
onPressed: () => print('hi'),
shape: StadiumBorder(),
color: Theme.of(context).primaryColor,
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 12, top: 6, bottom: 6),
child: CircularProgressIndicator(
backgroundColor: Colors.white,
strokeWidth: 2,
),
),
Text('Loading'),
],
),
),
And this is how it looks like:
When I Add Padding it grows the button:
Are there any ways to achieve this automatically?
EDIT:
Just to make it clear, the end effect that I want is this:
Before and after the user presses the button:
I want the height to stay the same, automatically, without magic values inside a SizedBox.
This is totally possible. You wrap the CircularProgressIndicator inside a SizedBox to constrain it to that size. Also using MainAxisSize.Min in the Row prevents the button from trying to expand to infinite size.
ElevatedButton(
onPressed: (){},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue)),
child: isLoading
? Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("Loading"),
SizedBox(
width: 5,
),
SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.white),
backgroundColor: Colors.blue,
strokeWidth: 3,
),
)
],
),
)
: Text("Not Loading"))
This gives you the following
Looking at the CircularProgressIndicator source code, I can find there's a hardcoded minimum size of 36.0 height/width, so there's no way of getting smaller than that automatically.
I re-created your case and was able to see the CircularProgressIndicator properly inside the RaisedButton maintaining it's size.
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Progress Button',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Progress Button'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () => print('hi'),
shape: StadiumBorder(),
color: Theme.of(context).primaryColor,
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 12, top: 6, bottom: 6),
child: CircularProgressIndicator(
backgroundColor: Colors.white,
strokeWidth: 2,
),
),
Text('Loading'),
],
),
),
],
),
),
);
}
}
Output (both platforms):
you can use mainAxisAlignment: MainAxisAlignment.spaceBetween to make space between your widgets in Row.
You can wrap your Row widget to a Padding widget to make padding for whole content in your button as well.
Padding(
padding: EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircularProgressIndicator(
backgroundColor: Colors.white,
strokeWidth: 2,
),
Text('Loading'),
],
),
)