how to overlay a circular image on the top of a card (half in the card and half outside the card)? - flutter

I'm new to flutter and recently I tried to design a page where I have to put an image on the top of a card with half of it on the card and half of it outside the card, I tried Stack but couldn't design what I wanted!
here is an example of what I'm trying to design.
here is the code that isn't giving the desired result like the image below:
class ContainerWithCircle extends StatelessWidget {
final double circleRadius = 100.0;
final double circleBorderWidth = 8.0;
#override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Container(
width: circleRadius,
height: circleRadius,
decoration:
ShapeDecoration(shape: CircleBorder(), color: Colors.white),
child: Padding(
padding: EdgeInsets.all(circleBorderWidth),
child: DecoratedBox(
decoration: ShapeDecoration(
shape: CircleBorder(),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://upload.wikimedia.org/wikipedia/commons/a/a0/Bill_Gates_2018.jpg',
))),
),
),
),
Padding(
padding: EdgeInsets.only(top: circleRadius / 2.0),
child: Container(
// Some content
),
),
],
);
}
}

In order to create a layout like the one you specified, you can simply use a Stack and place the card with a padding to the top. Resources for you to look up: Stack, DecoratedBox & CircleBOrder. The following code shows an example implementation:
class ContainerWithCircle extends StatelessWidget {
final double circleRadius = 100.0;
final double circleBorderWidth = 8.0;
#override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: circleRadius / 2.0),
child: Container(
//replace this Container with your Card
color: Colors.white,
height: 200.0,
),
),
Container(
width: circleRadius,
height: circleRadius,
decoration:
ShapeDecoration(shape: CircleBorder(), color: Colors.white),
child: Padding(
padding: EdgeInsets.all(circleBorderWidth),
child: DecoratedBox(
decoration: ShapeDecoration(
shape: CircleBorder(),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://upload.wikimedia.org/wikipedia/commons/a/a0/Bill_Gates_2018.jpg',
))),
),
),
)
],
);
}
}

Related

Absolute positioning on the screen, and overlay of image of to the top portion of app

Absolute positioning on scaffold/screen.
1 - The white container in the 1st photo - how to align this as an absolute position on the bottom of the screen / how is it done as the best method?
2 - The container has to be overlaid on the top of the image.
Tried to give absolute positioning using stack on the screen/scaffold, didn't work.
Use the following code:
class SampleWidget extends StatefulWidget {
const SampleWidget({super.key});
#override
State<SampleWidget> createState() => _SampleWidgetState();
}
class _SampleWidgetState extends State<SampleWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://images.fineartamerica.com/images/artworkimages/mediumlarge/1/mountains-valleys-and-clouds-vertical-panorama-rick-deacon.jpg'))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(
height: 400,
),
Expanded(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 20.0),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: const Center(
child: Text(
"The new adventure begin here",
style: TextStyle(fontSize: 22),
)),
),
),
],
),
),
);
}
}
Output:

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:

Flutter - Problem about Transform with Network Image and Expanded Text

I'm trying to create a simple Container includes;
A text aligned to center left (that text can include 50 characters)
A network image which is aligned to bottom right, rotated a bit, and rounded.
I've written a code like this:
import 'package:flutter/material.dart';
class MyScreen extends StatefulWidget {
static const String idScreen = "myScreen";
#override
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("My Screen")),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 100,
alignment: Alignment.bottomRight,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadiusDirectional.circular(16.0),
color: Colors.yellow),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Baby",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
Transform(
child: Image.network(
"https://target.scene7.com/is/image/Target/Baby-210913-1631564062108?wid=315&hei=315&qlt=60&fmt=png",
fit: BoxFit.contain,
),
transform: Matrix4.rotationZ(-0.2),
alignment: FractionalOffset.centerRight,
),
],
),
),
),
],
),
);
}
}
But the output is:
In order to avoid white square in image, I tried to add my picture in Transform like:
Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.contain,
image: NetworkImage(
"https://target.scene7.com/is/image/Target/Baby-210913-1631564062108?wid=315&hei=315&qlt=60&fmt=png"
)
)
)
But flutter doesn't accept it in Transform widget. How can I solve this?
Also another problem; if I write "Baby" like "Baby Baby Baby Baby Baby Baby Baby Baby ", it gives overflow error. I tried to wrap my Text or Row with Expanded but didn't work. How can I solve this too?

Rounded corners Image inside PageView keeping ratio Flutter

I have a PageView with images list inside. I want to keep the image ratio and set a rounded corners to them.
Usually I had no problem to clip image inside simple list or single image.
But in this case, the ClipRRect is not wrapping the image and when I'm setting size to red Container nothing happened.
Result :
Code :
double maxiHeight = 250;
List<Widget> postList = [];
#override
void initState() {
for(Post p in Model.instance.postList) {
postList.add(post(p));
}
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
height: maxiHeight,
child: PageView(
controller: PageController(viewportFraction: 0.5),
children: postList
),
);
}
Widget post(Post post) {
return ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
margin: EdgeInsets.only(right: 10),
color: Colors.red,
child: Image.network(post.thumb, height: 50)
)
);
}
I want to keep my image ratio.
What am I missing here ?
About your code snippet, you are providing margin right 1st then wrapping with ClipRRect. Here the main Container is getting its size and then using margin, after wrapping with ClipRRect it is avoiding 10px from right to Clip. And this is how we are getting current output.
But we want padding outside The Container and without border radius. Means after decorating the image, just provide some padding. You can follow this and using fit: BoxFit.cover will cover the widget size.
Center(
child: Padding(
padding: EdgeInsets.only(right: 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
// margin: EdgeInsets.only(right: 10),// not here
color: Colors.red,
child: Image.network(
// post.thumb,
"https://unsplash.it/1440/3040?random",
// fit: BoxFit.fitHeight,
height: 150,
),
),
),
),
),
With the following modified code it should work:
#override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
height: 500.0,
child: ListView(scrollDirection: Axis.horizontal, children: postList),
),
);
}
Widget post(String uri) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.network(uri, fit: BoxFit.fitHeight)
),
);
}
Try to add BoxFit.cover to Image.network widget
Widget post(Post post) {
return ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
margin: EdgeInsets.only(right: 10),
color: Colors.red,
child: Image.network(post.thumb, height: 50, fit: BoxFit.cover,),
)
);
}

How to make a image fit in 1/3rd of screen in flutter

I want to create a layout like this where the users will select and image and it'll take them to another screen like below and the selected image will take about one-third portion of the screen. The rest 2/3rd will be used as a canvas as you can see.
Unfortunately this is what I've got till now:
Here's the entire code:
import 'package:flutter/material.dart';
import 'package:flutter_app/src/components/Canvas.dart';
import 'package:flutter_app/src/components/DrawingArea.dart';
class DetailsPage extends StatelessWidget {
List<DrawingArea> points = [];
final String imagePath;
final String title;
final int index;
DetailsPage(
{#required this.imagePath, #required this.title, #required this.index});
// Display the selected image
Widget displayImage(String imagePath) {
return Container(
child: Expanded(
child: Hero(
tag: 'logo$index',
child: Container(
margin: EdgeInsets.only(top: 20, right: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30)),
image: DecorationImage(
image: AssetImage(imagePath),
fit: BoxFit.cover,
),
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("This will be the canvas"),
),
body: Container(
child: Column(
children: <Widget>[
displayImage(imagePath),
],
),
),
);
}
}
You have to set height of container which you can set by using MediaQuery as shown below:
Past this function in your code
Widget displayImage(String imagePath) {
return Container(
height: MediaQuery.of(context).size.height / 3,
child: Expanded(
child: Hero(
tag: 'logo$index',
child: Container(
margin: EdgeInsets.only(top: 20, right: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30)),
image: DecorationImage(
image: AssetImage(imagePath),
fit: BoxFit.cover,
),
),
),
),
),
);
}
You can use Flexible: https://api.flutter.dev/flutter/widgets/Flexible-class.html
https://youtu.be/CI7x0mAZiY0
Column(children: [
Flexible(
flex: 1
child: Container(color: Colors.blue),
Flexible(
flex: 2
child: Container(color: Colors.green),
),
]);
Not sure if I got you right. Is this what you're trying to get?
Column(
children: [
Expanded(
flex: 1,
child: Image.asset(
'your_image_asset',
fit: BoxFit.cover,
),
),
Expanded(
flex: 2,
child: Placeholder(),
),
],
)