How to arrange boxes in row in Flutter? - flutter

This is my code to arrange boxes vertically.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
Widget box({width: 100.0, height: 100.0}) => Container(
width: width,
height: height,
color: Colors.grey,
);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
box(),
box(),
box(),
],
),
);
}
}
Since I have a little experience for CSS flexbox, replacing the Column widget with the Row to arrange boxes in row But it can't work. Only black screen appeared. I've already make sure that the code works under the MaterialApp widget.
For learning purpose, I want to keep the code as simple as possible.
What do I need to make the above code work? What is a minimum requirement? Or is there an other widget appropriates for root in such example case?
Thank you for sparing time to read my question!

You need a material app render the colors and stuff
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
box(),
box(),
box(),
],
),
);
);
}
}

MaterialApp widget must be a root widget
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: MyApp())); // <- magic
class MyApp extends StatelessWidget {
Widget box({width: 100.0, height: 100.0}) {
return Container(
width: width,
height: height,
color: Colors.grey,
);
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
box(),
box(),
box(),
],
),
);
}
}

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.

How to clip overflowing column widget contained by stack contained by column

There are two main widgets:
I have this OverflowingWidget that is basically a Column - in reality this contains many widgets - However for this example, it has been given a height bigger than its parent widget.
The Parent widget ContainerWidget is basically AnimatedSwitcher which is basically a Stack contained by Column which constrained by a hight less than OverflowingWidget.
As you can see in dart-pad there is an overflow. The OverflowingWidget.
import 'package:flutter/material.dart';
const 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: ContainerWidget(),
),
),
);
}
}
class ContainerWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
height: 100,
width: 50,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: ClipRect(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: OverflowingWidget(),
layoutBuilder: (currentChild, previousChildren) => Stack(
children: [
...previousChildren,
if (currentChild != null) currentChild,
],
)),
),
),
],
));
}
}
class OverflowingWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: [Container(color: Colors.blue, height: 150, width: 50)]);
}
}
Desired result:
I need the OverflowingWidget to be clean clipped without trying to resize the content inside. The same effect that can be obtained when in css:overflow:hidden.
AnimatedSwitcher is getting height 100, but it needs 150 for current widget. you can increase the height on redContainer.
Instead of using Column, you can use Stack widget.
class ContainerWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
height: 150,
width: 50,
child: Stack(
children: [
ClipRect(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: OverflowingWidget(),
layoutBuilder: (currentChild, previousChildren) => Stack(
children: [
...previousChildren,
if (currentChild != null) currentChild,
],
)),
),
],
));
}
}
I found a way to clip an overflowing column/row. Simply wrap that column/row with Wrap widget. That will do the clipping.
class OverflowingWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Wrap(children: [
Column(children: [
Container(
color: Colors.blue,
height: 150,
width: 50)
])
]);
}
}

How to put logo a little bit higher and add text above it

I'm new in flutter world. I'm trying to put a little bit this logo up and add text above it.
I found that I need Stack and Positioned Widget to position my logo and sure I can position this logo with i.e: top: 20, bottom: 20 etc but then I thought, I'm positioning it versus my emulator with certain height and weidth, what about devices with other resolutions? It should be dynamic I guess?
Could you tell me how can I achieve it?
Here is how it should looks:
How it looks now (dont mind about this logo, it's just an example)
And my another question. How can I add some text above this logo?
The code I wrote:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
backgroundColor: const Color(0xFEC2C2C2),
body: Stack(
children: <Widget>[
Positioned.fill(
child: Image(
image: AssetImage('assets/images/logo.png'),
),
),
],
),
),
),
);
}
try this code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(50.0),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('This is My Brand Name',
style: Theme.of(context).textTheme.headline5),
SizedBox(
height: 20.0,
),
FlutterLogo(
size: 150,
)
],
),
),
);
}
}
Demo: https://i.stack.imgur.com/FTPqh.jpg

How to positioned widget toLeftOf or toRightOf in Flutter

I first want to center one widget and then add another widget to the right of the center widget.
Currently, flutter APIs are not feasible for this. In android, it can be easily done in relative layout or constraint layout.
I tried with some hack with MediaQuery,
Stack(
children: [
Center(child: Text(17)),
Positioned(
bottom: 0,
left: (screenWidth / 2) + (screenWidth / 3),
child: Column(
children: []
)
)
How to try this in an easy way or a proper way.
You can use the Align widget for this.
Code Example
import 'package:flutter/material.dart';
class SandBox extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
width: 300,
height: 300,
color: Colors.blue,
child: Align(
alignment: Alignment.centerRight, //aligns the child widget to the right center
child: Text('17'),
),
),
),
);
}
}
Maybe, it can help you to achieve what you want:
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(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Text('17'),
),
Align(
alignment: Alignment.bottomRight,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
),
),
),
],
),
);
}
}
Or you can adjust it using some calculations using MediaQuery and Stack.
You can use badges package to achieve this goal.
Finally, I found used https://pub.dev/packages/align_positioned
AlignPositioned.relative(
Text(day.englishDate.toString(),
textScaleFactor: 3, style: dayTextStyle),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
....
],
),
moveByChildWidth: 1.1,
minChildWidthRatio: 1,
moveByChildHeight: 0.3)
Please use Align along with Row.
here is simple code to achieve this.
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: Stack(
children:[
Align(
child : Row(
mainAxisAlignment: MainAxisAlignment.center,
children:[
Padding(child: Text('Left'),padding: EdgeInsets.all(5)),
Text('Center widget'),
Padding(child: Text('Right'),padding: EdgeInsets.all(5))
]) ,
alignment: Alignment.center),
]
),
),
);
}
}
Here is the output:

Which layout structure should I code to match my app design

For my new Flutter project I've done some research on layouts, however it still is a bit vague.
Here is the layout I'd like to create:
After some research and watching some videos, it seems this is the MaterialApp code:
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Color(0xFF0E2E40),
title: Text('City Discovery'),
actions: [
Image.asset(
'assets/images/logoicon.png',
width: 35,
)
],
),
body: ListView(
children: [
introSection,
Image.asset(
'assets/images/barman.png',
width: 600,
height: 240,
fit: BoxFit.cover,
),
crimeSection,
mysterySection,
bottomSection,
],
),
),
);
}
But now defining the layout of the different Sections is quite hard.
From what I can tell, there should be:
ListView to make my page scrollable, which it should be
introSection: Container for XYZ with 2 rows for 2 text sections.
Image
crimeSection: Container for XYZ with 3 rows for 2 text sections and button. First text section divided into 2 colums for icon and text
mysterySection: Container for XYZ with 2 rows for 2 text sections. First text section divided into 2 columns for icon and text
bottomSection: Tabs? Although tabs only seem to be part of the appbar, so not sure what the alternative is
The closest example I could find, however changing the code doesn't get me anywhere:
https://github.com/flutter/website/blob/master/examples/layout/lakes/step6/lib/main.dart
For some reason containers can only have 1 child, so that probably means I need a row in my container which then has children which then has 2 childs for both text sections? Incredibly hard to code some simple UI.
If someone can help me with the code for the introSection and the bottomSection, I can probably work out the rest myself.
I recommend to create components folder for reusable widgets, as buttons, logos, text, etc.
If you have a widget that does not used in other components, you can separate it in the same file but use underscore, to make this widget private (It will be visible only inside this file). All that will make your code more readable.
About bottom tabs.
If you want to use it as bottom tabs, you can put it in bottomNavigationBar parameter of Scaffold widget. If you need to use in inside the ListView, it possible but you need to pass the exact height of the tab, because TabView trying to expand as much as possible, same as ListView.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: LayoutExample(),
);
}
}
class LayoutExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _BottomNavigationBar(),
body: ListView(
children: <Widget>[
_IntroSection(),
Placeholder(fallbackHeight: 200),
_CrimeSection(),
_MysterySection()
],
),
);
}
}
class _IntroSection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('Intro text1'),
Text('Intro text2')
],
),
);
}
}
class _CrimeSection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
height: 200,
child: Text('CrimeSection'),
);
}
}
class _MysterySection extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent,
),
),
height: 200,
child: Text('MysterySection'),
);
}
}
class _BottomNavigationBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
);
}
}