Flutter - How to make image responsive with all screen sizes - flutter

Hi I am making a book app in flutter which will have material buttons on top of the image per page. but I notice when I go from iPhone X to iPhone XR or any others, the buttons are all over the place and I see the picture isn't aligned correctly either or same. I need only the landscape mode picture to fill the whole page and be totally responsive on all screens including iPad....
how can I go about doing this..?
I tried media query but when I do screenSizes.width* any number what's happening is the buttons are not displaying and ... the image is scrolling infinitely and all screen sizes are still showing different images.
I will share my code below for one button and the image
#override
Widget build(BuildContext context) {
var screenSizes = MediaQuery.of(context).size;
return Scaffold(
appBar: new AppBar(title: new Text("1 Alif-laam-meem آلم, Pg2")),
body: new SingleChildScrollView(
child: Container(
constraints: BoxConstraints.expand(
// BoxConstraints
// BoxConstraints.expand(
// height: 1000,
// .expand(
width: screenSizes.width * 10,
height: screenSizes.height * 10,
),
// children: [
child: Stack(children: <Widget>[
SafeArea(
top: true,
bottom: true,
right: true,
left: true,
child: new Container(
// padding: EdgeInsets.zero,
child: new Image.asset(
"test/assets/quranpg0.png",
// fit: BoxFit.fitWidth,
fit: BoxFit.cover,
// color: Colors.purpleAccent,
// colorBlendMode:ui.BlendMode.colorDodge,
))),
Positioned(
// right: 600,
bottom: screenSizes.width * 0.985,
left: screenSizes.height * 0.87,
// bottom: 754.0,
// left: 360,
// left: width*0.5,
// top: 900,
// top: 100,
child: Opacity(
opacity: 0.95,
child: _visible
? MaterialButton(
// minWidth:screenSize.width*0.1,
// 0.1 = 10% of the screen , 0.5 = 50% of the screen
// ios sizes usually are 620...
// height: screenSize.height*0.1,
onPressed: () => changeTextArabic1(),
onLongPress: () => changeTextEnglish1(),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(80.0),
// child: Text(labels[i]),
),
child: Ink(
child: Text(surah0),
// disabledTextColor: Colors.transparent,
// color: Colors.cyan[300],
// // color: Colors.purple[300],
// highlightColor: Colors.blue,
// // shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(60.0)
// // ),
// textColor: Colors.white,
// color: Colors.cyan[400],
padding: EdgeInsets.only(
top: screenSizes.height * 0.05,
left: screenSizes.width * 0.02,
right: screenSizes.width * 0.02,
bottom: screenSizes.height * 0.05),
// EdgeInsets.all(21.0),
// left: 28, top: 25, right: 28, bottom: 25),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
// all together looks COOL royal Blue:
Colors.tealAccent[400],
Colors.cyan[900],
Colors.teal
// Color(0xff0E0077),
// Color(0xff1B00EE)
],
// begin: Alignment.centerLeft,
// end: Alignment.centerRight,
),
),
),
// color: Colors.blue[300],
// highlightColor: Colors.blue,
splashColor: Colors.cyan,
// ),
textColor: Colors.white,
)
: Container(),
),
),

If you need to determine the screen orientation, you can do it like so:
var orientation = MediaQuery.of(context).orientation;
For a fully working solution that will help you scale elements correctly, I strongly suggest exploring this repo: https://github.com/TechieBlossom/learning_platform_app
There's even a video series with explanations that accompany it:
https://www.youtube.com/watch?v=afBmGC63iIQ

Related

how can i make user assign look stacked?

I want each user to be stacked, neat as in the picture how can i make user assign look stacked? i want like this :
enter image description here
my result now :
enter image description here
my code :
Row(
children: List.generate(3, (index) {
return Column(
children: [
ClipRRect(
borderRadius:BorderRadius.circular(8),
child: Image.asset(
'asset/img/profile_photo.png',
width: 40,
height: 40,
),
),
],
);
}),
),
To make widgets stack on top of another, you need to use the Stack widget.
Stack(
children: List.generate(3, (index) {
return Padding(
padding: EdgeInsets.only(left: (index * 0.5) * 40), // distance from the left
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.asset(
'asset/img/profile_photo.png',
width: 40,
height: 40,
),
),
);
}),
),
Of course you need to use Stack to make everything looks stacked, not Row. You can use something like this:
#override
Widget build(BuildContext context) {
const WIDTH = 80.0;
return Scaffold(
body: Center(
child: Stack(
children: List.generate(7, (index) {
return Positioned(
left: (WIDTH - 30) * index,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
border: Border.all(color: Colors.black, width: 1.0*index),
),
width: WIDTH,
height: 40.0,
child: Text(index.toString()),
),
);
})),
),
);
}
Result:
Remember to calculate distance carefully. I use Positioned and calculate left distance = (WIDTH - 30) * index. It is kinda same as your images, just adjust few things, then OK. Good luck!
This is how i usually do stacked widgets like that. try it out
Stack(
clipBehavior: Clip.none,
children: [
for (var i = 0; i < yourList.length; i++)
Container(
//* you can adjust the margin here base on your desired output
margin: EdgeInsets.only(left: 12 * i.toDouble()),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.asset(
'asset/img/profile_photo.png',
width: 40,
height: 40,
),
),
),
]),

How to maintain container widget width when we add a child column widget

My code without column widget gives expected UI like this
But when I add a column widget the width of the container is shrinking based on the column widget child like this
Code:
Scaffold(
backgroundColor: Color(0xffE3E4EB),
appBar: AppBar(
titleTextStyle: TextStyle(fontWeight: FontWeight.w600),
backgroundColor: Color(0xffE3E4EB),
elevation: 0,
actions: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Container(
width: 60,
height: 60,
child: Icon(Icons.done),
),
)
],
),
body: Center(
child: Padding(
padding: EdgeInsets.only(top: 120, left: 20, right: 20, bottom: 40),
child: Container(
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(20)),
// child: Column( // disable this 3 line to check the UI
// children: [Text("Dinesh Nagarajan")],
// ),
),
),
),
);
How I can maintain the width of my container
You can just set the width property of container to double.infinity. It will expand to fit the maximum available width.

How to overlap two circles?

Can someone help me get this layout with the first circle over the second?
image
I have this function:
Widget overlapped() {
final overlap = 25;
final items = [
Container(
padding: EdgeInsets.only(right: 2),
decoration: new BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: CircleAvatar(
radius: 22,
backgroundImage: AssetImage('assets/example_logo.png'),
backgroundColor: Colors.black,
),
),
CircleAvatar(
radius: 22,
backgroundColor: Colors.white,
child: ClipOval(
child: Image.network(
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/1200px-Google_%22G%22_Logo.svg.png",
errorBuilder: (context, exception, stackTrace) {
return Container(color: Colors.white);
},
height: 35,
))),
CircleAvatar(
child: Text('+2', style: TextStyle(color: Colors.white)),
backgroundColor: Theme.of(context).canvasColor),
];
List<Widget> stackLayers = List<Widget>.generate(items.length, (index) {
return Container(
padding: EdgeInsets.fromLTRB(index.toDouble() * overlap, 0, 0, 0),
child: items[index],
);
});
return Stack(children: stackLayers);
}
This function whenever I add an item to the array, it adds a widget on the right. But I want the first to be above the second, the second of the third, etc ...
you could use the Stack widget :
Stack(
children:<Widget>:[
Positioned(
right: 130.0,
child:Container(
shape: BoxShape.circle,
)
),
Positioned(
left: 130.0,
child:Container(
shape: BoxShape.circle,
)
),
]
)
Use Stack and Positioned together.
import 'package:flutter/material.dart';
class OverLap extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Overlap'),
),
body: Container(
padding: const EdgeInsets.all(8.0),
width: 500.0,
child: Stack(
children: <Widget>[
//Change according to your icon
Icon(
Icons.flaky,
size: 50.0,
color: Colors.red,
),
Positioned(
left: 20.0,
//Change according to your icon
child: Icon(
Icons.flaky,
size: 50.0,
color: Colors.blue,
),
),
],
),
),
);
}
}

How to add responsiveness to Tablets through Positioned and padding widget?

I am trying to use MediaQuery within LayoutBuilder and for all Positioned - Material buttons I need to add different logic for tablets ,small phone and big phone and I want to add if and else statement for these through mediaQuery
this if statement is displaying a error when I put it under positioned.
#override
Widget build(BuildContext context) {
var deviceData = MediaQuery.of(context);
double _width = MediaQuery.of(context).size.width;
double _height = MediaQuery.of(context).size.height;
var screenSize = MediaQuery.of(context).size;
return LayoutBuilder(builder: (context, constraints) {
return OrientationBuilder(builder: (context, orientation) {
Size size = MediaQuery.of(context).size;
double width = size.width > size.height ? size.height : size.width;
if (MediaQuery.of(context).size.width > 600) {
isLargeScreen = true;
} else {
isLargeScreen = false;
}
SizeConfig().init(constraints, orientation);
Positioned (
// height: context.heightPct(.99),
// width: context.widthPct(.99),
// Container(
// alignment: Alignment(,-.3),
// child: FractionallySizedBox(
// widthFactor: 30,
if (isLargeScreen){
width: 213 * SizeConfig.imageSizeMultiplier,
height: 92 * SizeConfig.heightMultiplier,
}else{
height: 92 * SizeConfig.heightMultiplier,
width: 213 * SizeConfig.imageSizeMultiplier,
child: Opacity(
opacity: 0.9,
// left: width*0.5,
// top: 900,
// top: 100,
child: _visible
? MaterialButton(
// minWidth:screenSize.width*0.1,
// 0.1 = 10% of the screen , 0.5 = 50% of the screen
// ios sizes usually are 620...
// height: screenSize.height*0.1,
onPressed: () => changeTextArabic1(),
onLongPress: () =>
changeTextEnglish1(),
// shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(60.0)
// child: Text(labels[i]),
// ),
child: Ink(
child: Text(surah0),
// disabledTextColor: Colors.transparent,
// color: Colors.cyan[300],
// // color: Colors.purple[300],
// highlightColor: Colors.blue,
// // shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(60.0)
// // ),
// textColor: Colors.white,
// color: Colors.cyan[400],
padding: EdgeInsets.all(21.0),
// padding: EdgeInsets.only(
// left: 28,
// top: 25,
// right: 28,
// bottom: 25),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
// all together looks COOL royal Blue:
Colors.red,
Colors.blue,
// Color(0xff374ABE),
// Color(0xff64B6FF),
// Color(0xff0E0077),
// Color(0xff1B00EE)
],
// begin: Alignment.centerLeft,
// end: Alignment.centerRight,
),
),
),
// color: Colors.blue[300],
// highlightColor: Colors.blue,
// ),
textColor: Colors.white,
)
: Container(),
// ),
// ):Container()
),
}),
You can use:
isLargeScreen
? Positioned()
: Positioned()
or:
Positioned(
height: isLargeScreen ? something : something,
width: isLargeScreen ? something : something
)

Flutter UI breaks when "smallest width" is changed in developer options

I am new into flutter programming. I have been working on a certain UI as shown below.
If I attempt to change the "smallest width" option in the developer options and set to some other value than the default, the whole UI breaks as shown.
I must add that the middle area which got completely broken was a stack widget.
#override
Widget build(BuildContext context) {
return Consumer<SinglePlayerGameState>(
builder: (context, gameState, child) => Expanded(
flex: 48,
child: Container(
color: gameState.getGameColor(),
child: Center(
child: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
child: Transform.rotate(
angle: 45,
child: UNOcard(UNOcardData(CardTypes.BACK)),
),
top: -30,
left: 90,
),
Positioned(
child: Transform.rotate(
angle: 65,
child: UNOcard(UNOcardData(CardTypes.BACK)),
),
top: 20,
left: 50,
),
Positioned(
child: Transform.rotate(
angle: 180,
child: UNOcard(UNOcardData(CardTypes.BACK)),
),
top: 100,
left: 65,
),
Positioned(
child: Transform.rotate(
angle: 45,
child: UNOcard(UNOcardData(CardTypes.BACK)),
),
top: 10,
right: 10,
),
Positioned(
child: Transform.rotate(
angle: 65,
child: UNOcard(UNOcardData(CardTypes.BACK)),
),
top: 120,
right: 50,
),
Positioned(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.black),
child: Text(
"${gameState.playingCards.length}",
style: TextStyle(
fontSize: 20,
fontFamily: 'Frijole',
color: Colors.white),
),
padding: EdgeInsets.all(7),
),
top: 10,
left: 10,
),
Positioned(
child: SizedBox(
child: Center(
child: FlatButton(
onPressed: () {
gameState.nextTurn();
},
child: Icon(
FontAwesomeIcons.undoAlt,
size: 25,
),
color: Colors.white,
)),
height: 35,
width: 60,
),
bottom: 10,
left: 10,
),
Positioned(
child: DragTarget<UNOcardData>(
onWillAccept: (UNOcardData data) {
var res = isValidMove(
data, gameState.onGoingCards.last, gameState);
if(res){
print(res);
return true;
}else{
vibrate();
return false;
}
},
onAccept: (UNOcardData data) {
print(data);
performAction(data, gameState);
},
builder: (context, candidateData, rejectedData) =>
Transform.rotate(
angle: 0,
child: gameState.onGoingCards.last,
),
),
top: 60,
right: 100,
),
],
),
),
),
),
);
}
}
Like we use units like "vmin , vmax , vh " etc in html/css for responsive texts and sizes, what are the alternatives in flutter ? How do we responsive apps in flutter exactly ? I am not talking about scaling to other screen sizes, but to slightly different resolutions and logical pixel densities.
Thanks for your time.
That's because you are using margins from the edges with
Positioned(
child: Transform.rotate(
angle: 180,
child: UNOcard(UNOcardData(CardTypes.BACK)),
),
top: 100,
left: 65,
),
This top means that it's going to position itself 100 units from the top. What you actually want is some percentage offset from the center. You can do it like this:
Positioned.fill(
child: Align(
// (0, 0) is the center, (1, 1) is right bottom, (-1, -1) is left top and so on
alignment: Alignment(0.25, 0.25),
child: YOUR_WIDGET
)
);
For more responsive UI you can get screen_sizes with MediaQuery.of(context) or use a package like flutter_screenutil to scale your UI according to a sample, like for example 1080x1920 screen.