Flutter fitting image in container without stretching - flutter

I am using the following code but my image is stretching, regardless of the box fit value. Need help in making it fill the screen without stretching.
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: () => _optionsDialogBox(),
child: Container(
height: 250.0,
child: _companyLogo == null
? CircleAvatar(
radius: 75.0,
foregroundColor: Colors.deepOrange,
child: Icon(
Icons.camera_alt,
size: 75.0,
),
)
: Image.memory(
base64Decode(_companyLogo),
fit: BoxFit.cover,
),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 0.0),
blurRadius: 5.0,
spreadRadius: 1.0)
],
color: constructionOrange,
// gradient: GRADIENT,
),
),
),

I am very new to flutter but I have a logic in mind that can solve this:
let size of image be = w (width) * h (height)
let max size of container be = a (cont. width) * b (cont. height)
find the a/w and then multiply by h such that the size of new image will be a * (h*a/w)

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,
),
),
),
]),

Flutter half circle with multiple fill colors

I would like to create this in Flutter:
I know you can create a half circle like this.
But how I can get these multiple fill colors?
I know there is way to get this done with LinearGradient. (something like this)
But this might work, but I need to each color-section as a separated part/widget because I want to animate them in the next step.
How could I get this done?
You can do this using Custom Painter but then I understand it would be challenging to animate each color bar. I have been able to create something like you need
I used the ClipRRect widget to cut out the bottomLeft and bottomRight portions of a square -> SemiCircle.
Each Color bar is a Container and since you would like to animate each bar you can easily replace the Container with an AnimatedContainer and proceed from there. You might also need to make the widget stateful for animations.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
// Assuming constraints here.
// Play with width and height values
const double widgetWidth = 100;
const double widgetHeight = 60;
// To get a semicircle
const double bottomRadius = widgetWidth / 2;
//Since we have 5 colors . Each color bars height is 60/5 = 12
const double colorBarHeight = widgetHeight / 5;
return ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(bottomRadius),
bottomRight: Radius.circular(bottomRadius)),
child: SizedBox(
width: widgetWidth,
height: widgetHeight,
child: Column(
children: [
Container(
width: widgetWidth,height: colorBarHeight,color: Colors.green),
Container(
width: widgetWidth,height: colorBarHeight,color: Colors.orange),
Container(
width: widgetWidth,height: colorBarHeight,color: Colors.yellow),
Container(
width: widgetWidth, height: colorBarHeight, color: Colors.red),
Container(
width: widgetWidth, height: colorBarHeight, color: Colors.blue),
])));
}
}
Please try this below code:
class SemiCircle extends StatelessWidget {
const SemiCircle({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(300),
bottomRight: Radius.circular(300),
),
child: Container(
alignment: Alignment.center,
height: 100,
width: 200,
child: Column(
children: [
Container(
height: 10,
color: Colors.red,
),
Container(
height: 10,
color: Colors.yellow,
),
Container(
height: 10,
color: Colors.green,
),
Container(
height: 10,
color: Colors.red,
),
Container(
height: 10,
color: Colors.yellow,
),
Container(
height: 10,
color: Colors.green,
),
Container(
height: 10,
color: Colors.red,
),
Container(
height: 10,
color: Colors.yellow,
),
Container(
height: 10,
color: Colors.green,
),
Container(
height: 10,
color: Colors.red,
),
],
),
),
),
),
],
),
);
}
}
You will get an output like below:

Designing a Flutter button with image and text

If I just throw together an image and some text in a rounded-corner rectangle, the user will not know that they can "click here". But I don't have to bake my own solution. InkWell covers this scenario, complete with a nice shadow.
I am positioning
a custom clickable icon using the
InkWell
class, itself requiring to be inside an
Ink
instance.
import 'package:flutter/material.dart';
const boat_url = ('https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/'
'Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG/'
'182px-Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG');
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Image',
home: Scaffold(
backgroundColor: Colors.grey,
body: MyImage(),
)));
}
class MyImage extends StatelessWidget {
MyImage({Key key,});
#override
Widget build(BuildContext context) {
Size sz = MediaQuery.of(context).size * 0.4;
double border = 4;
return Stack(children: [
Positioned(
top: 100,
left: 100,
width: sz.width,
height: sz.height,
child: Material(
child: Ink(
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
new BoxShadow(
color: Colors.red,
blurRadius: 10.0,
offset: new Offset(30.0, 20.0),
),
],
border: Border.all(
color: Colors.blue,
width: border,
),
borderRadius: BorderRadius.circular(40),
),
child: InkWell(
onTap: (){/*..*/},
child: Column(
children: [
Container(
height: 4 * (sz.height - 2 * border) / 5,
alignment: Alignment.center,
child: Image.network(boat_url),
),
Container(
height: (sz.height - 2 * border) / 5,
child: FittedBox(
clipBehavior: Clip.antiAlias,
alignment: Alignment.centerLeft,
fit: BoxFit.fitHeight,
child: Text('A long descriptive sentence')),
)
],
)),
),
)),
]);
}
}
1- I'm not actually using Colors.white, and the Scaffold itself has
backgroundColor: Colors.grey. Where is the white background coming from?
2- When we talk of a "shadow", I'm expecting the shadow to be behind
the ink/inkwell object. Why does the shadow appear in front?
Related: 1
That white color is from the Material widget, to remove that you can use type param.
Material(
type: MaterialType.transparency,
child: Container(),
);
Here is code to achieve the custom button
Video link
Scaffold(
backgroundColor: Colors.blueGrey,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
color: Colors.green.shade200,
border: Border.all(color: Colors.green),
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
blurRadius: 5,
spreadRadius: 2,
color: Colors.black26,
)
]),
margin: const EdgeInsets.all(20),
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
splashColor: Colors.black26,
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Image.asset(
'assets/images/marked_tyre_base.png',
fit: BoxFit.cover,
width: 80,
height: 80,
),
const SizedBox(
height: 10,
),
Text(
'Tyre 1',
style: TextStyle(color: Colors.white),
)
]),
),
),
),
),
),
),
);
Screenshot:
Create a class, ImageTextButton:
class ImageTextButton extends StatelessWidget {
final VoidCallback onPressed;
final ImageProvider image;
final double imageHeight;
final double radius;
final Widget text;
ImageTextButton({
#required this.onPressed,
#required this.image,
this.imageHeight = 200,
this.radius = 28,
#required this.text,
});
#override
Widget build(BuildContext context) {
return Card(
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)),
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: onPressed,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Ink.image(
image: image,
height: imageHeight,
fit: BoxFit.cover,
),
SizedBox(height: 6),
text,
SizedBox(height: 6),
],
),
),
);
}
}
Usage:
ImageTextButton(
onPressed: () {},
image: AssetImage('chocolate_image'),
text: Text('Chocolate'),
)

Transparent card but with shadow effect from elevation

I'm having trouble making a card that has a transparent white color (opacity 0.4). But, with shadow from the elevation effect.
If I remove the elevation, there's no shadow effect and the card look transparent. But, if I add some elevation, the transparent effect ruined. Here's what I've tried:
Widget cardMenu(String title) {
return Container(
padding: EdgeInsets.symmetric(horizontal: UIComponent.componentPadding),
child: Stack(
alignment: Alignment.topCenter,
children: [
Positioned(
top: -100,
child: Container(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: Center(
child: Text(
title,
style: TextStyle(color: Colors.transparent),
),
),
),
)
),
Align(
alignment: Alignment.bottomCenter,
child: Card(
elevation: 0,
color: Colors.white.withOpacity(0.4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(UIComponent.cardButtonRadius),
),
),
child: Container(
height: 350,
width: 180,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: EdgeInsets.all(UIComponent.widgetPadding),
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: UIComponent.h1,
color: UIComponent.neutralDark,
),
),
)
],
),
),
),
)
],
),
);
}
The output of my code:
What I'm expecting to be:
Hii Christophorus Anindityo N
Make a class for BoxShadow property of container.
class CustomBoxShadow extends BoxShadow {
final BlurStyle blurStyle;
const CustomBoxShadow({
Color color = const Color(0xFF000000),
Offset offset = Offset.zero,
double blurRadius = 0.0,
this.blurStyle = BlurStyle.normal,
}) : super(color: color, offset: offset, blurRadius: blurRadius);
#override
Paint toPaint() {
final Paint result = Paint()
..color = color
..maskFilter = MaskFilter.blur(this.blurStyle, blurSigma);
assert(() {
if (debugDisableShadows)
result.maskFilter = null;
return true;
}());
return result;
}
}
And use this class in a Container
Container(
child: Center(
child: Container(
height: 200.0,
width: 300.0
decoration: BoxDecoration(
boxShadow: [
CustomBoxShadow(
color: Colors.black,
offset: Offset(5.0, 5.0),
blurRadius: 5.0,
blurStyle: BlurStyle.outer
)
],
),
child: Text("Transparent Card with Shadow", style:TextStyle(fontSize:15))),
)
)
Now you are good to code :)

Flutter multiple items in Row with Expanded/Flexible

I want to have more(in this example 4) items in Row. I tried use Expanded or Flexible or mainAxisAlignment: MainAxisAlignment.spaceEvenly to fill up all width of screen. But I want to heve items lets say specific width and height 50 pixels, and GestureDetector which is around item to be 1/4 of screen(4 items = full width). So everywhere I tap in the row something will be selected. My problem is that every my solution deforms items(circles) or circle must be very huge to width = height to not be deformed.
I also tried wrapping whole _ratingEmoji in Expanded and giving ratingItem.ratingIndicator constraints to max width but with same result.
Row of items:
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (var ratingItem in editGroceryRatingProvider.foodRatings)
_ratingEmoji(editGroceryRatingProvider, ratingItem, context),
],
),
Item:
Widget _ratingEmoji(EditGroceryRatingProvider editGroceryRatingProvider,
SelectedFoodRating ratingItem, BuildContext context) {
return GestureDetector(
child: ratingItem.selected
? Container(
width: MediaQuery.of(context).size.width / 8,
height: MediaQuery.of(context).size.width / 8,
padding: const EdgeInsets.all(2.0),
decoration: BoxDecoration(
border: Border.all(
color: Color(0xFF312ADB),
width: 3.0,
),
borderRadius: BorderRadius.circular(32.0)),
child: Center(
child: ratingItem.ratingIndicator,
),
)
: ratingItem.ratingIndicator,
onTap: () => editGroceryRatingProvider.updateSelectedRating(ratingItem),
);
}
RatingIndicator which is "circle" item to be on the screen:
Container(
decoration: BoxDecoration(
border: Border.all(
color: color,
width: 1.5,
),
borderRadius: BorderRadius.circular(64.0),
),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 3.0,
),
borderRadius: BorderRadius.circular(64.0),
),
child: ClipOval(
child: Container(
width: width ?? MediaQuery.of(context).size.width / 7,
height: height ?? MediaQuery.of(context).size.width / 7,
color: color,
),
),
),
);
Thanks a lot.
Update:
Items should stay as they are on screenshot, but "whole" row should be clickable(means even if you click between 2 items, one closer to click should be selected)
Check, please solution.
The whole area is clickable. You just need to add your item instead of mine.
#override
Widget build(BuildContext context) {
final colors = [Colors.red, Colors.blue, Colors.brown, Colors.cyan];
return Scaffold(
body: Container(
alignment: Alignment.center,
color: const Color(0xffFAFAFA),
child: Row(
children: List.generate(
colors.length,
(index) => Expanded(
child: GestureDetector(
onTap: () => print('Tapped:$index'),
child: Container(
height: 50,
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: colors[index],
),
),
)),
)),
),
),
);