I'm trying to let my users increase the size of an image inside a fixed size Stack.
The chosen size can be way above the Stack's size.
This is the result I get for now, even though the image :
Here is the relevant code :
Expanded(
child: AspectRatio(
aspectRatio: myCustomScreen.width / myCustomScreen.height,
child: ClipRRect(
borderRadius: BorderRadius.circular(14),
child: LayoutBuilder(
builder: (context, boxConstraint) {
return Stack(
alignment: Alignment.center,
fit: StackFit.passthrough,
children: [
Container(
color: Colors.blue,
),
//This object doesn't overflow when its width is above the
UnconstrainedBox(
child: Image(
width: (object.width.toDouble() * boxConstraint.biggest.width) / myCustomScreen.width,
image: NetworkImage("www.images.com/image.png", scale: 1)),
),
],
);
},
),
),
),
),
How can I let my users view the real size of the image inside this view without being constrained by the stack ?
Thank you !
Stack has a property called clipBehavior you can use it like this to enable overflow:
Stack(
clipBehavior: Clip.none,
// Your code continues here
Edit: Testing your code I made ti work on dart pad. The steps were, remove the UnconstrainedBox and used the image scale to resize it alongside with the fit property defined as none:
here's the code that I used on darted: https://dartpad.dartlang.org/
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> 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: [
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
Expanded(
child: AspectRatio(
aspectRatio: 200 / 400,
child: ClipRRect(
borderRadius: BorderRadius.circular(14),
child: LayoutBuilder(
builder: (context, boxConstraint) {
return Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
fit: StackFit.passthrough,
children: [
Container(
color: Colors.blue,
),
Image(
fit: BoxFit.none,
image: NetworkImage(
"https://images.pexels.com/photos/13406218/pexels-photo-13406218.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
scale: 1 / (_counter + 1),
),
),
],
);
},
),
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Related
How to make the children in the stack equal in height in flutter? The container below is the automatic height, I need to set the height of the upper container according to the height of the lower container.
Why do I need this?
Because I want to implement a background progress bar.
return Stack(
children: [,
Container(
//how to auto set this widget equal height to below.
height:?
),
Container(
child: Column(
children: [
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
);
Just wrap your Stack widget with IntrinsicHeight widget.
This will make each of the children of the Stack widget occupy the height of the largest child. So. all children will be of equal height.
As per the example you shared:
return IntrinsicHeight(
child: Stack(
children: [,
Container(
child: SomeWidget(),
),
Container(
child: Column(
children: [
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
)
);
I found the solution based on #JaisonThomas' comment.
return Stack(
children: [
Positioned.fill(
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
return Container(
child: Row(
children: [
Container(
width: constraints.maxWidth * _progress,
color: statusColor,
),
],
),
);
}),
),
Container(
child: Column(
children: [
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
);
Although there is a good solution that made by 'noveleven',
I implemented by using 'addPostFrameCallback' and 'key'.
(I added a background color for distinguish Widget.)
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> {
GlobalKey _key = GlobalKey();
double _sizeOfColumn = 0.0;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_sizeOfColumn = _key.currentContext.size.height;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return Stack(
children: [
Container(
color: Colors.grey,
height: _sizeOfColumn,
),
Container(
key: _key,
color: Colors.yellow,
child: Column(
mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("a"),
Text("b"),
Text("c"),
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
);
}
}
How can I place a container on top of other container's border like the image below?
What I'm doing is designing a background image to make it works but I just wonder can I make it without using any image as my background?
You can use Positioned widget inside Stack like this in order make place a Container on top of the other:
Scaffold(
body: SafeArea(
top: true,
child: SingleChildScrollView(
child: Stack(
overflow: Overflow.visible, // TO MAKE SECOND CONTAINER VISIBLE
children: [
Container(
height: 250.0,
color: Colors.green,
child: Center(child: Text("First Container")),
),
Positioned(
bottom: -25.0,
left: (MediaQuery.of(context).size.width/4),
width: 200.0,
height: 50.0,
child: Container(
color: Colors.red,
child: Center(child: Text("Second Container"))
),
)
],
),
),
)
);
I hope this answer will help you.
You can achieve this with Stack & Positioned widget as demonstrated in following code :
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> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: Stack(
overflow: Overflow.visible,
children: [
Container(
color: Colors.green,
width: MediaQuery.of(context).size.width,
height: 200,
child: Center(
child: Text("First Container"),
),
),
Positioned(
top: 175,
left: (MediaQuery.of(context).size.width / 2) - 100,
child: Center(
child: Container(
color: Colors.red,
width: 200,
height: 50,
child: Center(
child: Text("Second Container"),
),
),
),
),
],
),
);
}
}
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
Storycard(),
],
),
),
);
}
}
class Storycard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, int index) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
child: Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
child: Column(
children: <Widget>[
ClipRRect(
child: Image.asset(
news[index].image,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0)),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(news[index].newsHeadline,
style: GoogleFonts.ubuntu(
fontSize: 17, fontWeight: FontWeight.bold)),
)
],
),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NewsDetails(news: news[index])));
});
},
itemCount: news.length,
);
}
}
I am trying here to have a list of scrollable cards. I want space above the cards to add some text. SO I tried using column and have a text and Listview Bulider as children. But the emulator is showing blank screen.
When the StoryCard() is alone used as the body the output comes with widgets. I can't add anything above the Listview. Can someone help.
enter image description here
Use Expanded class or Flexible class for the ListView.
ListView requires a finite height for it's content.
With your current code, ListView is having infinite height, hence the error. Expanded or Flexible helps you to have the remaining space to be utilized for your child
Solution
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
// here is the change
Expanded(
child: Storycard()
)
]
)
)
);
}
}
Using Flexible
class StoryUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Stories'),
),
body: Column(
children: [
Text('Georgy'),
// here is the change
Flexxible(
fit: FlexFit.loose,
child: Storycard()
)
]
)
)
);
}
}
I want to achieve the following PhonePe UI in flutter. How can I make sure that the "Proceed" button always remains at the bottom position ?
Image
You can copy paste run full code below
You can use bottomSheet attribute of Scaffold
return Scaffold(
...
bottomSheet: Container(
width: MediaQuery.of(context).size.width,
child: RaisedButton(
child: Text('PROCEED'),
onPressed: () {},
),
),
);
working demo
full code
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: BottomSheetTestPage(),
);
}
}
class BottomSheetTestPage extends StatefulWidget {
#override
_BottomSheetPageState createState() => _BottomSheetPageState();
}
class _BottomSheetPageState extends State<BottomSheetTestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('bottom sheet'),
),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(index.toString()),
subtitle: Text("${index}"),
);
},
itemCount: 300,
),
bottomSheet: Container(
width: MediaQuery.of(context).size.width,
child: RaisedButton(
child: Text('PROCEED'),
onPressed: () {},
),
),
);
}
}
You will solve using Expanded widget.
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: MaterialButton(
onPressed: () => {},
child: Text(’Proceed'),
),
),
),
You can expand the first part of the layout
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Text('FirstPart')),
InkWell(
onTap: () => print('pushed'),
child: Container(
width: 100,
height: 60,
alignment: Alignment.center,
color: Colors.black26,
child: Text('PROCEED'),
),
)
],
);
}
}
You can use stack like this
Stack(
children: <Widget>[
//your other widgets here
Align(
alignment: Alignment.bottomCenter,
child: yourButton,
)
],
),
a simple way to do this is using a Scaffold since the scaffold has a bottomNavigationBar attribute that takes a widget then you can simply pass to it a button like this
Widget build(BuildContext context) {
return Scaffold(
// will always be at the bottom
bottomNavigationBar: FlatButton(onPressed: (){},child: Text("Proceed"),),
body: Text("your body goes here"),
);
}
I would like to shrink and expand my Wrap widget when the size of the parent Container is increased or decreased. The fonts of the individual children should increase or decrease along with the size of the boxes. What is the best way to achieve this?
I have tried FittedBox (scaledDown) which reduces the sizes but then widget doesn't wrap at all (!) and all the children remain on one line.
This is the default behavious (if the Wrap widget is defined in a Container with a specific size).
Here is the code...
Widget _build(BuildContext context) {
var words = ["a", "abc", "de", "ef", "g", "i", "is", "s", "th"];
return new Scaffold(
body: Column(children: <Widget>[
Text('height 100'),
Container(
color: Colors.red,
height: 100.0,
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: _buildWordButtons(words),
),
),
Text('height 50'),
Container(
color: Colors.green,
height: 50.0,
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: _buildWordButtons(words),
),
),
Text('FittedBox, scaleDown, height 200'),
Container(
color: Colors.blue,
height: 200.0,
child: FittedBox(
fit: BoxFit.scaleDown,
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: _buildWordButtons(words),
),
),
),
]),
);
}
List<Widget> _buildWordButtons(List<String> words) {
var buttons = List<Widget>();
for (var word in words) {
buttons.add(Container(
decoration: new BoxDecoration(border: new Border.all(color: Colors.black)),
child: Text(
word,
style: TextStyle(fontSize: 50.0),
),
margin: EdgeInsets.all(5.0),
));
}
return buttons;
}
If you'd like to create a Text widget that will adapt to the size of its parent widget, you may want to look into LayoutBuilder widget. Using this widget should help its child widget determine its parent widget's constraints. Since you've mentioned that having a spacious Container should print long texts in a newline, you can have it set inside the LayoutBuilder.
Here's a sample. I've modified the code snippet provided.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#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> {
final words = ["a", "abc", "de", "ef", "g", "i", "is", "s", "th"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(children: <Widget>[
Text('height 100'),
Container(
color: Colors.red,
height: 100.0,
child: adaptiveText(),
),
Text('height 50'),
Container(
color: Colors.green,
height: 50.0,
child: adaptiveText(),
),
Text('height 200'),
Container(
alignment: Alignment.center,
color: Colors.blue,
height: 200.0,
child: adaptiveText(),
),
]),
);
}
adaptiveText() {
return LayoutBuilder(
builder: (context, constraints) {
debugPrint('constraint maxHeight: ${constraints.maxHeight}');
// adapt Text widget if parent widget size is <= 100
if (constraints.maxHeight <= 100)
return FittedBox(
fit: BoxFit.scaleDown,
child: Wrap(
alignment: WrapAlignment.spaceEvenly,
children: _buildWordButtons(words),
),
);
else
return Wrap(
alignment: WrapAlignment.spaceEvenly,
children: _buildWordButtons(words),
);
},
);
}
List<Widget> _buildWordButtons(List<String> words) {
var buttons = List<Widget>();
for (var word in words) {
buttons.add(Container(
decoration:
new BoxDecoration(border: new Border.all(color: Colors.black)),
child: Text(
word,
style: TextStyle(fontSize: 50.0),
maxLines: 3,
),
margin: EdgeInsets.all(5.0),
));
}
return buttons;
}
}
Demo