How to make an image fill out its parent container? - flutter

I want my image to fill exactly half of my screen, and in the bottom row i want to add some more widgets. I tried to make the rows spaceAround so that equal space is given. On adding image widget to row, small image was displayed. I added a SizedBox.expand parent to the image and gave the image BoxFit.fill fit, and then the entire image disappeared all together. How do I fix this problem?
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context){
final view = Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
children: <Widget>[
SizedBox.expand(
child: Image.asset('assets/airb.jpeg'),
)
],
),
Row(
children: <Widget>[
],
)
],
);
return Scaffold(
appBar: AppBar(
title: Text('Image')
),
body: view,
);
}
}

If I got it right, from your description, you would like to have an image on the top half of your screen and then some other widgets below it.
Usually when I do things relative to the size of a container (or relative to the screen size), I'm using LayoutBuilder which will tell you the size constraints that it has (like maxHeight, maxWidth). One thing tho, be careful with it because sometimes these constraints can be =infinity (if you wrap the LayoutBuilder inside a ```Row/Column``
Now for your case you can use the following code snippet:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: LayoutBuilder(builder: (context, constraints) {
return Column(
children: <Widget>[
Container(height: constraints.maxHeight / 2, color: Colors.red), // replace this with an image
//Add extra widgets here.
Text("this will be below image")
],
);
}));
}
Note, the code is a simple example on how to do the sizing, you will have to add the widgets that you need and customise them :).

This may help you-
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final view = Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Expanded(
flex: 5,
child: Row(
children: <Widget>[
new Image.asset(
"images/pitch.png",
fit: BoxFit.cover,
),
],
)),
Expanded(
flex: 5,
child: Row(
children: <Widget>[],
)),
],
);
return Scaffold(
appBar: AppBar(title: Text('Image')),
body: view,
);
}
}

Related

Display aspect ratio item and image in a row in flutter

Let's say that I want create a Flutter app. In my app I want to create a Row widget with the following children:
AspectRatio(aspectRatio: 1, child: Center(child: Text("I am text!"))
Image.asset("path/to/asset.png") with unknown aspect ratio
I want to display that Row while keeping both aspect ratios intact. How can I do that?
Here is my attempt:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("This is my app")),
body: Container(
child: Row(children: [buildItem1(), buildItem2()]),
),
);
}
Widget buildItem1() {
return AspectRatio(
aspectRatio: 1,
child: Container(
color: Colors.red, child: Center(child: Text("This is my text"))));
}
Widget buildItem2() {
return Image.asset("path/to/my/asset.jpg");
}
}
And this is what being displayed:
I am trying to figure out a way to automatically shrink the row height such that both items would fit the screen.
If I use a fixed hight like that:
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("This is my app")),
body: Container(
height: 300,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [buildItem1(), buildItem2()],
),
),
);
}
...
Than I get the following:
Which is better, but I want to fill the entire width of the screen.
Thanks for anyone who can help!
You can use Expanded on second widget, that will get the avialable space on row. Also for the image use fit: BoxFit.cover(better looks than width).
body: Container(
height: 300,
child: Row(
children: [buildItem1(), Expanded(child: buildItem2())],
),
),
Widget buildItem2() {
return Image.asset(
"assets/images/user.png",
fit: BoxFit.cover,
);
}
Now if you want full screen, I will prefer
Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Container(
color: Colors.red,
child: Center(
child: Text("This is my text"),
)),
),
Expanded(
child: Image.asset(
"assets/images/user.png",
fit: BoxFit.cover,
)),
],
),
Also LayoutBuilder on scaffold's body provide more options. Also check IntrinsicHeight.

My costume widget is not showing in a Column

So i have created a costume widget and i wanted to show it in a column, but whenever i put it in a column and run the application the widget doesn't show on the screen.
This is my costume Widget
#override
Widget build(BuildContext context) {
return new FractionallySizedBox(
widthFactor: 1,
heightFactor: 0.3,
child: Container(
child: new LineChart(linechartData()),
margin: EdgeInsets.fromLTRB(0, 10, 0, 0),
),
);
}
and this is my main.dart widget
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("hello"),
),
body: new Container(
child: new Column(
children: [
new Container(child: new Text("hello")),
new Chart()],
)),
),
);
}
}
Ive tried to check if the problem is with the column widget by removing my costume widget from the column widget and by putting a text widget but the text widget shows fine the problem is when i add my costume widget inside it that everything desapears
You need to wrap your widget inside the Flexible one, like this:
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("hello"),
),
body: new Container(
child: new Column(
children: [
new Flexible(child: Costume()),
new Chart()],
)),
),
);
}
}
CHeckout FractionallySizedBox (Flutter Widget of the Week) video
You can wrap the FractionallySizedBox with Expanded to get available height and then heightFactor will be used its child
body: Container(
child: Column(
children: [
Container(
child: new Text("hello"),
),
Expanded(
child: FractionallySizedBox(
widthFactor: 1,
heightFactor: 0.3,
child: Container(
),
),
)
],
),
),
Also you might be interested on LayoutBuilder

Flutter : Why Text Widget on Flutter automatically centered when placed before TextField Widget ? ( Inside Column Widget )

So i tried to make my TextWidget aligned to left but when i put TextWidget above ( before ) TextFieldWidget it's automatically become centered following with the TextFieldWidget, here my code
import 'package:flutter/material.dart';
void main() {
runApp(new MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Center(
child: Text("SQLite Application"),
),
),
body: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Text("Name of Things"),
TextField()
],
),
),
);
}
}
and here is the result :
Code Output
Is there a solve to make the TextWidget to aligned to the left ? I've tried to use TextAlign.left on TextWidget but it wont change.
Use
crossAxisAlignment: CrossAxisAlignment.start,
on the Column
You need to set the mainAxisAlignment to Start
Column(
crossAxisAlignment: CrossAxisAlignment.start
In case you want to place the contents at the Right Side, you can use
Column(
crossAxisAlignment: CrossAxisAlignment.end
just add
Column(
crossAxisAlignment: CrossAxisAlignment.start,
the result
You put your text inside Column widget. Column by default crossAxisAlignment is centre. That's why your text is always on centre.
for example
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children:const [
SizedBox(
height: 20,
),
Text("your text....!"),
TextField()
],
),
And if you wanna align text without Column, use Align with with alignment.topleft. It will move on left side
Align(
alignment: Alignment.topLeft,
child: Text("Name of Things", textAlign: TextAlign.left,),
),

Add scrollable and refreshable data table between fixedWidth widgets

Totally I need a scrollable DataTable with refresh possibility on pull down between header and footer fixed width widgets.
I have a widget, using on every page in my app. THis widget return a Scaffold with appbar and body like column (). This widget used like CommonPage(title, widgetsArrayForBodyColumn) from other widgets.
For now I need to use a follow widgets in that body:
Lookup (for filtering or for example, any fixed height widget)
DataTable (for show data)
Card (to show another data)
DataTable should be scrollable and refreshable on pull down.
I tried many different ways, but still has no success. My last solution is using stack, but list hidden beside the card.
I can't understand how to achieve my goal: have refreshing datatable between non scrollable widgets in a column.
class CommonPage extends StatefulWidget {
final String title;
final List<Widget> children;
const CommonPage({
Key? key,
required this.title,
required this.children,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
...
body: Column(children: [
FixedHeightWidget(),
PageScreen(),
]);
}
}
class PageScreen {
#override
Widget build(BuildContext context) {
return CommonPage(
title: Title,
children: [
FixedHeightWidget(),
PageList(),
],
);
}
}
class PageList {
Widget build(BuildContext context) {
//TODO Return fixedWidthWidget at top, expandedRefreshableScrollableDataTable, fixedWidthWidget at bottom
}
}
My current solution: (almost achieves my goal, but as mentioned card hides part of list and no ways to scroll and check bottom of the list):
return Expanded(
child: Stack(
children: [
RefreshIndicator(
onRefresh: onRefresh,
child: ListView(
children: [
listItems.isNotEmpty
? DataTable(...)
: Container(),
],
),
),
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
alignment: Alignment.bottomCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 5),
child: Card(...),
),
),
),
],
),
],
),
);
I found the solution:
return Expanded(
child: Column(
children: [
Expanded(
child: RefreshIndicator(
onRefresh: onRefresh,
child: ListView(
children: [listItems.isNotEmpty
? DataTable(...)
: Container(),
],
),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 5),
child: Card(...),
),
],
),
);

How to scale a Text widget that would behave like a scaling of an image

I would like to perform an Hero transition that will change, at the end, the size of a Widget.
This widget contains some text.
By default, the text widget will resize and the text inside move and resize to fit the text widget.
I would like to make to whole widget behave like an image would do : Everything will scale (zoom).
I tried :
auto_size_text package : The text will still move and the result is not perfect
screenshot package : It take too long to generate the image, replace the current widget with the image before performing the hero transition.
I am thinking about RenderRepaintBoundary, but this seems a lot of work for a simple task.
Any idea ?
If I understand what you want to achieve, you may want to use FittedBox.
This is what I used to create the animation below, where the Text widgets have a different size between the beginning and the end of the animation:
Thanks to #Romain, the easy answer was indeed FittedBox.
Making a Hero transition that will change the size of a Text Widget will be smooth when I put a FittedBox on the second page.
But I needed to pass down the original size to the second page to make the Text inside the FittedBox appear on the same number of lines that it was previously displayed.
Here the result :
https://vimeo.com/346745092
Here the code :
import 'package:flutter/material.dart';
const String textThatCouldChangeDependingOnContext = "Hero Text .... ";
main() {
runApp(MaterialApp(home: MyHomePage()));
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey _textKey = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(64.0),
child: Column(
children: <Widget>[
Hero(
tag: 'tag',
child: Material(
child: Container(
color: Colors.red,
child: Text(textThatCouldChangeDependingOnContext,
key: _textKey),
),
),
),
FlatButton(
child: Text('Fly'),
onPressed: () {
Size originalTextSize = _textKey.currentContext.size;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
MySecondPage(originalTextSize)));
},
)
],
),
),
),
);
}
}
class MySecondPage extends StatefulWidget {
final Size originalTextSize;
MySecondPage(this.originalTextSize);
#override
_MySecondPageState createState() => _MySecondPageState();
}
class _MySecondPageState extends State<MySecondPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: () => Navigator.pop(context),
child: Hero(
tag: 'tag',
transitionOnUserGestures: true,
child: Material(
child: Container(
color: Colors.red,
child: FittedBox(
fit: BoxFit.contain,
child: SizedBox(
height: widget.originalTextSize.height,
width: widget.originalTextSize.width,
child: Text(textThatCouldChangeDependingOnContext),
),
),
),
),
),
)
],
),
),
);
}
}