How to make a fixed blurring overlay in Flutter? - flutter

I would like to implement this overlay bar
This is what i reached lately (i just want to blur the part below the overlay bar portion, everything else is not a problem)
The crucial part is that it must blur the portion of screen below itself. I have no clue about how should i do it, i tried everything (like setting up a transparent container and blur it, but the transparent color turns out to be black :/ ).
This is how i currently implement the navigation bar with a container over it:
Widget _navigationBarAndOverlay() {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
OverlayBarWidget(),
_navigationBar(),
],
);
}
And this is the OverlayBarWidget code:
Widget build(BuildContext context) {
return Container(
color: Colors.transparent,
height: 85,
width: MediaQuery.of(context).size.width,
child: Center(child: Text("Nothing to do"),),
);
}
Thanks in advance for your help!
EDIT:
In the end i managed to do it just few minutes later, so i won't assign the best answer.
The solution is using a Stack instead of a Column: the overlay part will actually overlay the interface instead of being put below. In order to do it, you need to give your bottomAppBar a precise dimension (use a SizeBox, as below) and use a Positioned for the overlay bar positioning
Stack(
children: <Widget>[
Scaffold(
body: TabBarView(
controller: tabController,
...
),
bottomNavigationBar: SizedBox(
height: 57,
child: _navigationBar(),
),
),
Positioned(
bottom: 57,
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaY: 16, sigmaX: 16),
child: OverlayBarWidget(),
),
),
)
)
Final result

You can try BackDropFilter
This kind of effects are relatively expensive, use them with caution!
Important: Wrap your container with ClipRect widget, otherwise the entire screen will take the BackDropFilter effect.
ClipRect(
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/your-image.png'),
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
child: Container(
color: Colors.black.withOpacity(0.0),
),
),
),
)
Play with the values to get different effects
sigmaX: 5.0
sigmaY: 5.0
withOpacity: 0.0
Making a comparison, at this point you get something like this:
Now, if you want to display information over that image, you can just use the previous code in a Stack(), and add some Positioned() Text()
Stack(
children: <Widget>[
ClipRect( ... ),
Positioned(top: 30, left: 30, child: Text("Some Info"),
Positioned(top: 60, left: 30, child: Text("Some more Info"),
], )
You can get something like this
BackDropFilter documentation
Flutter video about BackDropFilter --> https://youtu.be/dYRs7Q1vfYI

Related

Flutter - Add Progress bar or Shapes on image

I want to make a widget where i can add a progress bar or shapes inside a image.
As in the attachment,
I wrapped the image and the shape inside the Stack widget but when the screen sizes change the position of the widgets change too
Is there any way to achieve this ?
You can set the image as the decoration image of a Container. Then you can use a FractionallySizedBox for the item that should be placed inside the image, and set this widget as the Container's child. You can also use a Flex and set the text and shape (the items inside the image) as its children.
Container(
width: 300,
height: 300,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://images.vexels.com/media/users/3/151609/isolated/preview/1e5e087078b86c2491300c61ce46c48c-canning-jar-stroke-icon-by-vexels.png'),
fit: BoxFit.cover),
),
child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Align(
alignment: Alignment.bottomCenter,
child: FractionallySizedBox(
heightFactor: 0.6,
widthFactor: 0.6,
child: Flex(
direction: Axis.vertical,
children: <Widget>[
Flexible(
flex: 2,
child: Container(
child: Text(
'50%',
style: TextStyle(fontSize: 24),
)),
),
Flexible(
flex: 8,
child: Container(
child: Image.network(
'https://images.vexels.com/media/users/3/129171/isolated/preview/c3746ad76845f55dda5e6a0d1c81d32a-3-stack-coins-icon-by-vexels.png'),
),
),
],
)),
),
),
),
Result:
If you have screens size issue than use
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
you can get height or width of screen and adjust view according to this.

Flutter align widget horizontaly and verticaly

I am working on a Flutter project. I'm trying to create a widget like the image below and I can't manage to do it.
So what I'm trying to do, is to create a widget with a Text at the top left (the size of this widget is not constant and depends on the text in it).
I'm trying to align 2 other widgets with the Text:
The Widget 1 is aligned horizontaly and centered with the Text widget and at its right with no space between
The Widget 2's right edge is aligned verticaly with the Text widget's right edge, and is positioned under it (and there is no space between the 2 widgets).
I tried to implement this with Column and Row widgets or with a GridView but I couldn't manage to do so.
Also the overall size of this custom widget has to be shrinked.
Does someone know how to do something like that ?
Thank you.
This works
Container(
width: double.infinity,
height: 300,
color: Colors.grey[200],
child: Column(
children: <Widget>[
Row(
children: [
Flexible(
flex: 2,
child: Container(
height: 200,
color: Colors.blue,
),
),
Flexible(
flex: 1,
child: Container(
height: 100,
color: Colors.green,
),
),
],
),
Row(
children: <Widget>[
Flexible(
flex: 2,
child: Align(
alignment: Alignment.centerRight,
child: Container(
width: 150,
height: 100,
color: Colors.orange,
),
),
),
Flexible(
flex: 1,
child: Container(),
),
],
),
],
),
),

Icon widget cut off by Image widget

I'm trying to implement a "Change my profile picture" icon like how it appears in the profile page in Whatsapp, where a clickable camera icon hovers on the bottom right of the image.
This is the code I used inside a stateful widget:
Row(
children: <Widget>[
Stack(
children: <Widget>[
Container(
width: 120,
child: Image(
image: AssetImage('affogato.png'),
),
),
Positioned(
top: 70,
left: 90,
child: FloatingActionButton(
child: Icon(Icons.camera_alt),
onPressed: () {},
),
),
],
),
],
),
Strangely, the Icon seems to take the constraints of the Image container. So when I set the width as 120 and try to push the Icon button to the bottom right edge of the Image, it gets cut off by the Image constraints. How do the constraints of the Container affect the FloatingActionButton even though they're siblings inside the Stack not parent-child widgets? And how can I fix this so that the Icon can float over the edge of the image?
You can probably make use of height property of Positioned widget and adjust other dimensions (left, bottom, right, top) so that the button isn't cut-off at bottom right edge and is displayed properly. Working sample code below:
return Scaffold(
body: Center(
child: Row(
children: <Widget>[
Stack(
children: <Widget>[
Container(
width: 120,
child: Image(
image: AssetImage('assets/Icon-512.png'),
),
),
Positioned(
bottom: 0,
right: 0,
left: 78,
height: 35,
child: FloatingActionButton(
child: Icon(Icons.camera_alt),
onPressed: () {},
),
),
],
),
],
),
)
// This trailing comma makes auto-formatting nicer for build methods.
);
You might need to adjust dimensions per your need, but this way it doesn't cut-off the button.
Hope this answers your question.
Here's how I did it. I removed the Positioned widget completely and used Padding instead. It seemed to solve the problem. I also wrapped the image in a CircleAvatar to complete the Whatsapp style.
Row(
children: <Widget>[
Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: CircleAvatar(
radius: 70,
backgroundColor: Colors.greenAccent,
child: Container(
height: 150,
width: 150,
child: ClipOval(
child: Image(
image: AssetImage('lib/rainy.png'),
),
),
),
),
),
Padding(
padding: EdgeInsets.only(left: 105, top: 80),
child: Container(
width: 50,
height: 50,
child: FloatingActionButton(
backgroundColor: Colors.green,
child: Icon(Icons.camera_alt),
onPressed: () async {},
),
),
),
],
),
],
),

Why does Backdrop filter blur my entire app

I am trying to achieve a very similar effect to what was shown in the widget of the week video on flutter's channel: https://www.youtube.com/watch?v=dYRs7Q1vfYI#t=1m20s
On the right you see the desired result, on the left you see what's currently going on in my app.
The code I've been using is pretty similar to the one from the example video, using a Stack to position the Backdrop filter over my image. The rounded image and the blur over it are inside one widget, which will is placed inside another stack (along with the text at the bottom). Since I applied the filter only a small section of the image, I don't understand why entire app is blurred. Here's the code for the Image Widget:
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size.width - 75;
return Container(
height: size,
width: size,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Image(imageUri: "...", size: size - 30), // this is just a container with the image
Positioned(
top: 100,
left: 100,
bottom: 100,
right: 100,
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 5,
sigmaY: 5,
),
child: Container(
color: Color(0x66FF0000),
),
),
)
],
),
);
}
}
It turns out the video is missing an important part from the documentation:
If there's no clip, the filter will be applied to the full screen.
So the solution is to wrap the filter into a ClipRect, as taken from the example:
ClipRect( // <-- clips to the 200x200 [Container] below
child: BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: 5.0,
sigmaY: 5.0,
),
child: Container(
alignment: Alignment.center,
width: 200.0,
height: 200.0,
child: Text('Hello World'),
),
),
),
Another solution in 2021:
Apply clipBehavior: Clip.hardEdge to parent of BackdropFilter
Container(
clipBehavior: Clip.hardEdge,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0),
child: Container(
color: Colors.black.withOpacity(0.2),
),
),
)
Explanation:
clipBehavior: Clip.hardEdge means overflow: none
If no clip, filter will overflow upward (in widget tree) until they meet clip.

Flutter layout issue

I'm testing out flutter, but ran into an issue trying to create a specific layout. I'm trying to create a card with 2 parts. At the top is an image spanning the full width of the card and with a set height. Below that is a Container with several Text widgets laid out in a Column. I then wish to add some padding to the bottom container and offset it so it overlaps the bottom of the image.
I've tried doing this using a Stack, see the code below, but my issue is that from what I understand the Stack widget takes it size from all non-positioned widgets. This means the Stack only gets the size of the image and the Container gets cut of at the bottom of the image. The content of the Container is also of variable length, so I can not set a fixed height, but need the card to size itself to it's content, both the image and the Container.
return Card(
child: Stack(
children: <Widget>[
Image.network(
"https://imbo.vgc.no/users/e24/images/5f2fdecdbd09cfad22aa84e922a3e7c7?t%5B0%5D=crop%3Awidth%3D4027%2Cheight%3D2263%2Cx%3D0%2Cy%3D356&t%5B1%5D=maxSize%3Awidth%3D990&t%5B2%5D=resize%3Awidth%3D990&accessToken=e04754e3d904710cb41dc49bb02df916894bdf5a801c49a5965195cee3c86936",
height: 200.0,
),
Positioned(
top: 175.0,
left: 10.0,
right: 10.0,
child: Container(
color: Colors.fromRGBO(0, 0, 0, 1.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("This is the header", style: TextStyle(color: Color.fromRGBO(255, 255, 255, 1.0), fontSize: 20.0)),
Text("This is some content of variable length", style: TextStyle(color: Color.fromRGBO(255, 255, 255, 1.0)))
],
),
),
)
],
),
);
This is a simple version of my code, I've tried all sorts of different variations without achieving what I wish. I would appreciate any help or hints to guide me in the right direction.
Did you try to set overflow ?
Stack(overflow: Overflow.visible ...
You can use Transform.translate Widget to "move up" your Container into to the Image.
Transform.translate{
offset: Offset(xAxisOffset, yAxisOffset),
child: //your Container
}
Check out the Flutter Widget of the Week Video here: https://www.youtube.com/watch?v=9z_YNlRlWfA or read the Documentation for more information about the Widget: https://api.flutter.dev/flutter/widgets/Transform-class.html
You have to add
alignment: Alignment.bottomCenter for Stack widget.
Refer below code:
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Card(
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
Image.network(
"https://imbo.vgc.no/users/e24/images/5f2fdecdbd09cfad22aa84e922a3e7c7?t%5B0%5D=crop%3Awidth%3D4027%2Cheight%3D2263%2Cx%3D0%2Cy%3D356&t%5B1%5D=maxSize%3Awidth%3D990&t%5B2%5D=resize%3Awidth%3D990&accessToken=e04754e3d904710cb41dc49bb02df916894bdf5a801c49a5965195cee3c86936",
height: 200.0,
),
Positioned(
left: 10.0,
right: 10.0,
child: Container(
color: Colors.blueGrey,
child: Column(
children: <Widget>[
Text("This is the header",
style: TextStyle(
color: Color.fromRGBO(255, 255, 255, 1.0),
fontSize: 20.0)),
Text("This is some content of variable length",
style: TextStyle(
color: Color.fromRGBO(255, 255, 255, 1.0)))
],
),
),
)
],
),
),
),
),
);
}
Output: