Flutter Image bigger than container - flutter

How can I make it so that if an image that is rotated and goes outside of its container does not show outside of it?
I would also like that if the image is in a normal position and if it is larger than its container, it will be shown cut off.
By the way, can I do the same treatment with the icons?
Here is my code
class CardList extends StatelessWidget {
const CardList({
Key? key,
required this.text,
required this.subText,
required this.trailing,
}) : super(key: key);
final String text;
final String subText;
final Widget trailing;
#override
Widget build(BuildContext context) {
GlobalKey _container = GlobalKey();
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 0,
color: Theme.of(context).colorScheme.surfaceVariant,
margin: EdgeInsets.symmetric(horizontal: 0.5.w, vertical: 0.5.h),
child: Row(
children: [
Container(
padding: EdgeInsets.only(left: 10.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AutoSizeText(text,
maxLines: 1,
style: Theme.of(context).textTheme.bodyText1),
subText.isNotEmpty
? AutoSizeText(
subText,
maxLines: 1,
style: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(
color: Theme.of(context)
.colorScheme
.onSurfaceVariant,
fontWeight: FontWeight.w500),
)
: const SizedBox(
height: 0,
),
],
),
),
Container(
color: Colors.blue,
height: 100,
child: Transform.translate(
offset: Offset(0.0, 15.0),
child: Transform.rotate(
angle: -3.14 / 12.0,
child: Image.asset(
'assets/images/map.png',
height: 300,
))),
),
],
));
}
}

By using Container's clipBehavior and set it to antiAlias you can make sure the child widget never appear outside of its parent, like this:
Container(
clipBehavior: Clip.antiAlias, // add this
decoration: BoxDecoration(// add this
color: Colors.blue,
),
height: 100,
child: Transform.translate(
offset: Offset(0.0, 15.0),
child: Transform.rotate(
angle: -3.14 / 12.0,
child: Image.asset(
'assets/images/map.png',
height: 300,
))),
),

Try wrapping your image widget inside ClipRRect widget, ClipRRect.

Try below code hope its help to you, refer ClipRRect, just change my image with your image
FittedBox(
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Container(
constraints: BoxConstraints.tight(const Size(100, 100)),
color: Colors.blue,
child: Transform.translate(
offset: const Offset(0.0, 15.0),
child: Transform.rotate(
angle: -3.14 / 12.0,
child: const FlutterLogo(size: 300),
),
),
),
),
),
Result->

Using ClipRRect Widget will solve that.
If you wrap your image inside a ClipRRect Widget in a rotation position, it will automatically cut the outward edges.
ClipRRect(child: Image.network('your image'))
Also, in a normal image position inside a container, if the corners are rounded and the image is not, you need to put your image inside a ClipRRect widget, and borderRadius option allows you to round your image to match the container radius.
Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5)),
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Image.network('Your Image')
)
)

Related

Center Image In Container's child column flutter

I want to align image in center in column and increase size of image.
My desired look
This is what I got by using code
Here is my code:
class BigRoundedContainer extends StatelessWidget {
final String image, text;
const BigRoundedContainer({Key? key, required this.image, required this.text}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
width: 145.w,
height: 145.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(Dimensions.radius40),
color: Colors.white,
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black.withOpacity(0.5),
blurRadius: Dimensions.radius10,
offset: const Offset(0.0, 10),
)
],
),
child: Padding(
padding: EdgeInsets.only(bottom: Dimensions.height10),
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Expanded(
child: Image.asset(
image,
color: AppColors.fIconsAndTextColor,
),
),
SmallText(text: text, size: Dimensions.height20),
]),
),
);
}
}
This is how im using BigRoundedContainer
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
BigRoundedContainer(
image: "assets/images/agency.png",
text: LanguageStringKeys.instance.agency.tr,
),
BigRoundedContainer(
image: "assets/images/freelancer.png",
text: LanguageStringKeys.instance.freelancer.tr,
),
),
],
While you are using Expanded, you can skip size params on Image. Include fit: BoxFit.cover
Expanded(
child: Image.asset(
image,
fit: BoxFit.cover,
),
),
try this:
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Image.asset(
image,
color: AppColors.fIconsAndTextColor,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: SmallText(text: text, size: Dimensions.height20),,
)
you can play with SmallText's padding to get your desire space.
Give padding all in parent container then give image width height and margin between the text

When using Flutter Container, everything ok but no ripple effect - but Ink draws beyond its parent

I want to provide a few buttons inside a singlechildscrollview
Column(
children: < Widget > [
SizedBox(height: constraints.maxHeight / 8.0),
AnimationConfiguration.staggeredList(
position: 1,
duration: const Duration(milliseconds: 2000),
child: SlideAnimation(
verticalOffset: constraints.maxHeight / 10,
child: FadeInAnimation(
child: Image.asset('images/mylive.png'),
),
),
),
Flexible(
child: Padding(
padding: EdgeInsets.fromLTRB(
50, 20, 50, constraints.maxHeight / 7),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(10),
child: Wrap(
spacing: 25,
runSpacing: 25,
children: const < Widget > [
ButtonCard(
name: "My News",
imgpath: "open-email.png",
count: 0),
and this is the build method for the ButtonCard:
Widget build(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
final double height = MediaQuery.of(context).size.height;
return InkWell(
onTap: () {},
child: Container( <<--->> Ink(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
boxShadow: const [
BoxShadow(
color: Colors.black38,
offset: Offset(0, 2),
blurRadius: 7,
),
],
),
child: Column(
children: [
Stack(
children: [
Image.asset(
"assets/images/$imgpath",
width: 60,
),
],
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
name,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
],
),
),
);
}
When I use the container in ButtonCard, then everything is okay, but the InkWell does not show the ripple effect (because of the BoxDecation color set)
This results in the following, correct scroll view:
But when I change the Container to Ink - I get the beautiful ripple effect, which I want to have. But then the following error occurs during scolling:
As you can see, the Ink with its boxdecoration paints over the parents border. Is this a bug in Ink or does anyone know what the problem is here? Thanks!
In General cases:
Wrap the Container with Inkwell
Wrap the Inkwell with Material
Show needed color with Material
Set color to the Container as transparent
With the above settings, you can have a ripple effect with Inkwell. But very difficult to achieve when you're having gradient colors.
Ref: https://flutteragency.com/inkwell-not-showing-ripple-effect-in-flutter/
You must have Material -> Inkwell -> Ink

Ripple does not cover text

I figured I can draw ripple over an image by enclosing the image in Ink(decoration: BoxDecoration(image: ...)), but how can I do the same for Text?
This is supposed to be a card with an image on top and a title and some other information at the bottom:
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final post = _postModel.post;
return Material(
color: theme.colorScheme.background,
child: InkWell(
onTap: () {},
splashColor: Colors.red,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (post.imageUri != null)
// This image IS covered by the ripple (what I need)
AspectRatio(
aspectRatio: 5 / 3,
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
image: DecorationImage(
image: NetworkImage('https://picsum.photos/700'),
fit: BoxFit.cover,
),
),
),
),
// This must be underneath the ripple, but isn't.
Text(post.title, style: theme.textTheme.headline5),
Container(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 5),
color: Colors.transparent,
height: 60,
child: Row(
children: <Widget>[
// This is also covered by the ripple
Ink(
height: 35,
width: 35,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage('https://picsum.photos/100'),
),
),
),
SizedBox(width: 5),
// This must be underneath the ripple but isn't
Ink(
// decoration: Decoration,
child: Text(
post.author,
style: theme.textTheme.caption,
),
),
Spacer(),
],
),
),
],
),
),
),
);
}
When I press, the ripple covers both images as expected, however, I can't figure out how to make the ripple cover the text widgets as well. I tried wrapping the text in an Ink widget (the last one), but it doesn't work - the text is still displayed over the ripple.
Unpressed:
Pressed (the text is visible):

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 :)