How to create glass widget in flutter app? - flutter

I need to make glass card view widget in the flutter (like image).
Its mode without using the package. But if there is no solution, if there is a package for it, thank you for introducing that package as well.

Try to used glassmorphism package also refer glassmorphism_ui

You can use GLASS package.
This package is Null safety and also supports ANDROID IOS LINUX MACOS WEB WINDOWS platform.

class GlassMorphismExample extends StatelessWidget {
const GlassMorphismExample({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: Center(
child: GlassMorphism(
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.height * 0.8,
child: const Text(
"Glass Morphism",
style: TextStyle(fontSize: 35),
),
),
end: 0.5,
start: 0.3,
),
),
);
}
}
class GlassMorphism extends StatelessWidget {
final Widget child;
final double start;
final double end;
const GlassMorphism({
Key? key,
required this.child,
required this.start,
required this.end,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ClipRRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.white.withOpacity(start),
Colors.white.withOpacity(end),
],
begin: AlignmentDirectional.topStart,
end: AlignmentDirectional.bottomEnd,
),
borderRadius: const BorderRadius.all(Radius.circular(10)),
border: Border.all(
width: 1.5,
color: Colors.white.withOpacity(0.2),
),
),
child: child,
),
),
);
}
}
Result

thanks to all. I wrote my own package for answer of my question.
https://pub.dev/packages/flutter_glass

Related

Flutter Material elevation in Special form

I have a special clipper form (picture)
and I want to create a shadow around it. For that, I tried it with this:
Material(
elevation: 10,
child: ClipPath(
clipper: RoundedDiagonalPathClipper(),
child: Transform.scale(
scaleX: 1,
scaleY: -1,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(
25.0,
),
),
color: Colors.white,
),
...... more code, not important for this ....
But then it creates a normal container around the special form. I found the option "clip Behaviour, but I don't know if this is my solution. Can you help me? Or is there a other way of creating a shadow around this box?
A simple way is creating a Shadow and shifting your clipper by offset.
Create a ClipShadowPath class like this.
import 'package:flutter/material.dart';
#immutable
class ClipShadowPath extends StatelessWidget {
final Shadow shadow;
final CustomClipper<Path> clipper;
final Widget child;
ClipShadowPath({
#required this.shadow,
#required this.clipper,
#required this.child,
});
#override
Widget build(BuildContext context) {
return CustomPaint(
key: UniqueKey(),
painter: _ClipShadowShadowPainter(
clipper: this.clipper,
shadow: this.shadow,
),
child: ClipPath(child: child, clipper: this.clipper),
);
}
}
class _ClipShadowShadowPainter extends CustomPainter {
final Shadow shadow;
final CustomClipper<Path> clipper;
_ClipShadowShadowPainter({#required this.shadow, #required this.clipper});
#override
void paint(Canvas canvas, Size size) {
var paint = shadow.toPaint();
var clipPath = clipper.getClip(size).shift(shadow.offset);
canvas.drawPath(clipPath, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Here is usage:
Widget buildBodyWidget(BuildContext context) {
return ClipShadowPath(
////*** Your Custom clip path *****
clipper: RoundedDiagonalPathClipper(),
/// Blur property of Shadow class
shadow: Shadow(
blurRadius: 5
),
child: Transform.scale(
scaleX: 1,
scaleY: -1,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(
25.0,
),
),
color: Colors.white,
),
);
}

Custom widget, blur 2 widgets with text on front

I made my own widget with blur, bottom widget is looking correct, but top isn't. On top widget, text is behind blur, but why?
I need same result like second widget. (Text front of blur)
Second widget is looking correct.
Please look screenshot at first.
How to fix it? Thanks for any help.
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// incorrect
MyCard(
imageLink:
'https://catherineasquithgallery.com/uploads/posts/2021-02/1612198837_120-p-fioletovii-fon-mainkraft-160.png',
text: 'AR-scene',
),
SizedBox(
height: 70,
),
//correct
MyCard(
imageLink:
'https://www.digiseller.ru/preview/1019450/p1_3193057_f7ad4eea.jpg',
text: 'Photos',
),
],
),
);
}
}
// my custom widget
class MyCard extends StatelessWidget {
final imageLink;
final text;
const MyCard({Key? key, required this.imageLink, required this.text})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
width: 270,
height: 320,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 4, sigmaY: 3),
child: Center(
child: Text(
text,
style: TextStyle(fontSize: 25, color: Colors.white),
textAlign: TextAlign.center,
),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7),
image: DecorationImage(
fit: BoxFit.cover, image: NetworkImage(imageLink))),
);
}
}
Wrap your BackdropFilter with ClipRect, else it covers the covering the full screen.
return Container(
key: ValueKey(text),
width: 270,
height: 320,
child: ClipRect( //<- here
child: BackdropFilter(
More on BackdropFilter-class
Using backdrop filter applies that particular filter to the whole screen. You can use ClipRRect to make it adopt the size of child widget (Container in this case).
// my custom widget
class MyCard extends StatelessWidget {
final imageLink;
final text;
const MyCard({Key? key, required this.imageLink, required this.text})
: super(key: key);
#override
Widget build(BuildContext context) {
return ClipRRect(
child: Container(
width: 270,
height: 320,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 4, sigmaY: 3),
child: Center(
child: Text(
text,
style: TextStyle(fontSize: 25, color: Colors.white),
textAlign: TextAlign.center,
),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7),
image: DecorationImage(
fit: BoxFit.cover, image: NetworkImage(imageLink))),
),
);
}
}
A better solution is to use ImageFiltered instead of BackdropFilter widget.
ImageFiltered blurs its child, for example, a single picture.
BackdropFilter blurs everything "behind" it, but does not blur its own child. It's useful in situations like a pop-up dialog, where you want to blur the whole screen, except the dialog itself.

Flutter Container Overlay Widget

I want to get an image like the one below with Flutter. How should I provide this? I can provide this with container border, but I want to put a wigdet instead of border. For example, I want to wrap a circle widget with a Circleprogress bar. progress should grow as widget grows
Stack(
children: [
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: context.themeCopyExtensions.backgroundColor,
shape: BoxShape.circle,
border: Border.all(width: 5),
boxShadow: [
BoxShadow(
color: context.themeCopyExtensions.backgroundColor,
blurRadius: 10)
]),
child: ImagesHelper.imagesHelper.getAssetImage(imageName: "logo"),
),
],
);
I implemented using 'Stack' widget and 'CircularProgressIndicator'.
(Need to adjust each widget size)
/// Flutter code sample for CircularProgressIndicator
// This example shows a [CircularProgressIndicator] with a changing value.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
/// AnimationControllers can be created with `vsync: this` because of TickerProviderStateMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget>
with TickerProviderStateMixin {
AnimationController controller;
#override
void initState() {
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 5),
)..addListener(() {
setState(() {});
});
controller.repeat(reverse: true);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 300,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
CircularProgressIndicator(
value: controller.value,
strokeWidth: 5,
semanticsLabel: 'Linear progress indicator',
),
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFF431CEE),
),
child: Icon(
Icons.audiotrack,
color: Colors.white,
size: 35,
),
),
],
),
),
],
),
),
);
}
}
I think I would use the FloatingActionButton to do this. You can put it anywhere in the widget tree and achieve your intended goal with much less effort than creating custom painter. It will always sit on top of your whole stack of pages using its built in overlay functionality. If you also don't want it to be clickable, you can always set the onPressed to null. One possible example is:
FloatingActionButton(
onPressed: () {},
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: context.themeCopyExtensions.backgroundColor,
shape: BoxShape.circle,
border: Border.all(width: 5),
boxShadow: [
BoxShadow(
color: context.themeCopyExtensions.backgroundColor,
blurRadius: 10,
)
],
image: DecorationImage(
image: ImagesHelper.imagesHelper.getAssetImage(imageName: "logo"),
fit: BoxFit.cover,
)),
),
)

How to add swiper dots to the image

I am trying to add swiper dots below as shown in the figure
while in the code I tried parallax effect on image and text, now I am trying to add dots below, swiper dots will help to understand which page we are in.
here is the present code:
import 'package:ecommerce_int2/models/product.dart';
import 'package:flutter/material.dart';
import 'package:transformer_page_view/transformer_page_view.dart';
import 'package:flutter/cupertino.dart';
class ParallaxMain extends StatefulWidget {
ParallaxMain({Key key, this.title}) : super(key: key);
final String title;
#override
_ParallaxMainState createState() => new _ParallaxMainState();
}
class ParallaxSlide extends StatelessWidget {
final List<Product> product;
ParallaxSlide({Key key, this.product}) : super(key: key);
#override
Widget build(BuildContext context) {
return new TransformerPageView(
loop: true,
viewportFraction: 0.8,
transformer: new PageTransformerBuilder(
builder: (Widget child, TransformInfo info) {
return new Padding(
padding: new EdgeInsets.all(10.0),
child: new Material(
elevation: 4.0,
textStyle: new TextStyle(color: Colors.white),
borderRadius: new BorderRadius.circular(10.0),
child: new Stack(
fit: StackFit.expand,
children: <Widget>[
new ParallaxImage.asset(
//images[info.index],
product[info.index].image[0],
position: info.position,
),
new DecoratedBox(
decoration: new BoxDecoration(
gradient: new LinearGradient(
begin: FractionalOffset.bottomCenter,
end: FractionalOffset.topCenter,
colors: [
const Color(0xFF000000),
const Color(0x33FFC0CB),
],
),
),
),
new Positioned(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new ParallaxContainer(
child: new Text(
product[info.index].name,
style: new TextStyle(fontSize: 15.0),
),
position: info.position,
translationFactor: 300.0,
),
new SizedBox(
height: 8.0,
),
new ParallaxContainer(
child: new Text("₹ "+product[info.index].price.toString(),
style: new TextStyle(fontSize: 18.0)),
position: info.position,
translationFactor: 200.0,
),
],
),
left: 10.0,
right: 10.0,
bottom: 10.0,
)
],
),
),
);
}),
itemCount: product.length,
);
}
}
class _ParallaxMainState extends State<ParallaxMain> {
#override
Widget build(BuildContext context) {
return new SizedBox(
height: 400,
child: new ParallaxSlide()
);
}
}
Is there any way to add swiper dots to this code?
Try this:
move your TransformerPageView inside a stack and add a DotIndicator
Stack(children:[
TransformerPageView(controller: _controller),
DotsIndicator(controller: _controller)
])
Make sure you add the same _controller for both of them. Then position the dot indicator as you like.
PageController: A controller for PageView.
A page controller lets you manipulate which page is visible in a PageView.
You can read the complete information in the link provided.
Hints taken from here.
Personally, I use smooth_page_indicator because it provides awesome transition effects. Just follow the docs and it's so easy to implement.
Yes we can do it by using carousel_slider
Please check the example of Image carousel slider with a custom indicator.

How to make cutout icon with background in Flutter?

I'd like to achieve following effect in Flutter with built in Flutter widgets without using PNG image with transparency.
I was trying to experiment with backgroundBlendingMode but without success.
I can also think of using custom painter to draw circle and inner cross, but ideally I would like to use any Icon or any other Widget to cut the background.
I also stumbled upon something called CustomClipper. Is it the way to go?
Let's say that we have following widget:
return Stack(
children: <Widget>[
SizedBox(
height: 44,
width: 44,
child: Image.network(
'https://images.pexels.com/photos/1295138/pexels-photo-1295138.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
fit: BoxFit.cover,
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
top: 0,
child: Icon(
Icons.close,
color: Colors.black,
),
),
],
);
Sample image can be taken from pexels.
Ok, so I found the answer on SO in this question.
It appears that the proper keyword is cutout.
So my solution is really simple and looks like follows:
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Cutout(
color: Colors.white,
child: Icon(
Icons.close,
color: Colors.white,
),
),
),
And the clipper using ShaderMask:
class Cutout extends StatelessWidget {
const Cutout({
Key key,
#required this.color,
#required this.child,
}) : super(key: key);
final Color color;
final Widget child;
#override
Widget build(BuildContext context) {
return ShaderMask(
blendMode: BlendMode.srcOut,
shaderCallback: (bounds) =>
LinearGradient(colors: [color], stops: [0.0]).createShader(bounds),
child: child,
);
}
}