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,
),
);
}
Related
I am making an app project in Flutter, where I want a blurred background Bottom Navigation Bar. How can I implement a bottom navigation bar in scaffold with blurred background property?
My code of Scaffold in Flutter
You can use the below one as widget and change background as image or color you wish and remove unwanted params as per you need.
class GlassBox extends StatelessWidget {
final double blurRadius, cornerRadius, width, height;
final Border outline;
final BoxShadow shadow;
final Color backgroundColor;
final Widget child;
const GlassBox({
Key? key,
this.width = 100,
this.height = 100,
this.blurRadius = 4.0,
this.cornerRadius = 10,
required this.child,
required this.outline,
required this.shadow,
this.backgroundColor = const Color(0x44ffffff),
}) : super(key: key);
#override
Widget build(BuildContext context) {
final double blurSigma = blurRadius * 0.57735 + 0.5;
final borderRadius = BorderRadius.circular(cornerRadius);
return Container(
width: width,
height: height,
child: Stack(
clipBehavior: Clip.none,
children: [
ClipPath(
clipper: _InvRRectClipper(cornerRadius),
child: Container(
decoration: BoxDecoration(
borderRadius: borderRadius,
boxShadow: [
if (shadow != null) shadow,
],
),
),
),
Container(
decoration: BoxDecoration(borderRadius: borderRadius),
clipBehavior: Clip.antiAlias,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: blurSigma, sigmaY: blurSigma),
child: Container(color: const Color(0x0), child: child),
),
),
Container(
foregroundDecoration:
BoxDecoration(border: outline, borderRadius: borderRadius),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: borderRadius,
),
),
],
),
);
}
}
class _InvRRectClipper extends CustomClipper<Path> {
final double radius;
_InvRRectClipper([this.radius = 12]);
#override
Path getClip(Size size) {
final p = Path()
..addRRect(RRect.fromLTRBR(
0,
0,
size.width,
size.height,
Radius.circular(radius),
))
..addRect(Rect.largest)
..fillType = PathFillType.evenOdd;
return p;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
I'm trying to create a shape using flutter.
I tried to use some solutions but it didn't work. can anyone help thanks
An solution with ClipPaths, Stacks and ImageFiltered widgets.
This design is challenging to implement, but it is definitely doable. The three parts, the red shape, white bottom border and shadow must be clipped with an ClipPath.
All of these requires an ClipPath with a CustomClipper, I provide an simplified example, using a cubic curve.
But for making an exact path you can investigate the answer in this question, it might be helpful: How can i make this shape in Flutter
Then there is coordinating the position of these three parts inside a Stack widget.
Example
import 'dart:ui';
import 'package:flutter/material.dart';
class CustomHeader extends StatelessWidget {
final Function() onTap;
final Color backgroundColor;
final Color borderColor;
final Color shadowColor;
final Color splashColor;
final double height;
final Widget? child;
const CustomHeader({
Key? key,
required this.height,
required this.onTap,
this.child,
this.backgroundColor = const Color(0xFFD50000),
this.splashColor = const Color(0xFFCCFFCC),
this.borderColor = Colors.white,
this.shadowColor = Colors.black26,
}) : super(key: key);
#override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
return Stack(
children: [
// The shadow effect
Padding(
padding: const EdgeInsets.only(top: 18.0),
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 2, sigmaY: 2),
child: ClipPath(
clipper: CustomHeaderClipper(
startHeight: height * 0.75,
endHeight: height * 0.18
),
child: Container(
width: width,
height: height * 0.76,
color: shadowColor
),
),
),
),
// The white border
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: ClipPath(
clipper: CustomHeaderClipper(
startHeight: height * 0.75,
endHeight: height * 0.18
),
child: Container(
width: width,
height: height * 0.75,
color: borderColor,
),
),
),
// The red shape
ClipPath(
clipBehavior: Clip.antiAliasWithSaveLayer,
clipper: CustomHeaderClipper(
startHeight: height * 0.68,
endHeight: height * 0.2
),
child: Material(
color: backgroundColor,
child: InkWell(
onTap: onTap,
splashColor: splashColor,
child: SizedBox(
width: width,
height: height * 0.8,
child: child,
),
),
),
),
],
);
}
}
class CustomHeaderClipper extends CustomClipper<Path> {
final double startHeight;
final double endHeight;
const CustomHeaderClipper({
required this.startHeight,
required this.endHeight
});
#override
Path getClip(Size size) {
double height = size.height;
double width = size.width;
return Path()
..moveTo(0, 0)
..lineTo(0, startHeight)
..cubicTo(width * 0.35, height, width * 0.5, height * 0.4, width, endHeight)
..lineTo(width, 0)
..lineTo(0, 0)
..close();
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
class CustomHeaderBackgroundScreen extends StatelessWidget {
const CustomHeaderBackgroundScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height / 2.2;
return Scaffold(
backgroundColor: Colors.grey[200],
body: SafeArea(
child: CustomHeader(
height: height,
onTap: () {},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text("Your widget logic", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
),
),
),
);
}
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) => const MaterialApp(home: CustomHeaderBackgroundScreen());
}
void main() => runApp(const App());
Result
Here is how it is running on Chrome
Note on Accessibility
Different screen sizes and system preferences on text size might make this design hard to accommodate for, especially for getting the text sized well with this right aligned style, so be aware of this.
You can create the shapes using the CustomPaint widget together with BezierCurves. Here you can find out how to use BezierCurves with 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
Using stroke method, how to create gradient line with sharp end in flutter? I want to draw the line as below in flutter.
Use CustomPainter to draw:
import 'package:flutter/material.dart';
void main() => runApp(Example());
class Example extends StatefulWidget {
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: CustomPaint(
size: Size(200, 5),
painter: CurvePainter(),
),
)));
}
#override
void dispose() {
super.dispose();
}
}
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.black;
paint.style = PaintingStyle.fill; // Change this to fill
var path = Path();
path.moveTo(0, 0);
path.quadraticBezierTo(size.width / 2, size.height / 2, size.width, 0);
path.quadraticBezierTo(size.width / 2, -size.height / 2, 0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
modified sleepingkit answer:
import 'package:flutter/material.dart';
class PointedLinePainter extends CustomPainter {
final double width;
PointedLinePainter(this.width);
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.white;
paint.style = PaintingStyle.fill;
var path = Path();
path.moveTo(0, 0);
path.quadraticBezierTo(width / 3, 0.5, width, 0);
path.quadraticBezierTo(width / 3, -0.5, 0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
somewhere in code:
Container(
margin: EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
width: MediaQuery.of(context).size.width,
height: 2,
child: CustomPaint(
painter:
PointedLinePainter(width - 2 * horizontalPointedLineMargin),
),
)
Can't see your picture.You can use the CustomPaint widget to draw lines, define a class that extends CustomPainter, and use the canvas.drawLine() method.
Divider class
A thin horizontal line, with padding on either side.
In the material design language, this represents a divider. Dividers can be used in lists, Drawers, and elsewhere to separate content.
To create a divider between ListTile items, consider using ListTile.divideTiles, which is optimized for this case.
The box's total height is controlled by height. The appropriate padding is automatically computed from the height.
[![// Flutter code sample for Divider
// This sample shows how to display a Divider between an orange and blue box
// inside a column. The Divider is 20 logical pixels in height and contains a
// vertically centered black line that is 5 logical pixels thick. The black
// line is indented by 20 logical pixels.
//
// !\[\](https://flutter.github.io/assets-for-api-docs/assets/material/divider.png)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: MyStatelessWidget(),
),
);
}
}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>\[
Expanded(
child: Container(
color: Colors.amber,
child: const Center(
child: Text('Above'),
),
),
),
const Divider(
color: Colors.black,
height: 20,
thickness: 5,
indent: 20,
endIndent: 0,
),
Expanded(
child: Container(
color: Colors.blue,
child: const Center(
child: Text('Below'),
),
),
),
\],
),
);
}
}]
Here info how to change style enter link description here
Row(
children: [
Expanded(
child: SizedBox(
height: 3,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.black],
begin: Alignment.centerRight,
end: Alignment.centerLeft
)
),
),
),
),
Expanded(
child: SizedBox(
height: 3,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.black],
begin: Alignment.centerLeft,
end: Alignment.centerRight
)
),
),
),
),
],
)
I am creating a story app where two users telling the story like this in the below images. so here I want to create a dialog box like the below image. but I don't know how to create
You should be implement below way
class IntroPage extends StatefulWidget {
#override
State<StatefulWidget> createState() => _IntroPageState();
}
class _IntroPageState extends State<IntroPage>
with SingleTickerProviderStateMixin {
AnimationController animationController;
bool _menuShown = false;
#override
void initState() {
animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 500));
super.initState();
}
#override
Widget build(BuildContext context) {
Animation opacityAnimation =
Tween(begin: 0.0, end: 1.0).animate(animationController);
if (_menuShown)
animationController.forward();
else
animationController.reverse();
return Scaffold(
backgroundColor: Colors.amberAccent,
body: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
right: 0,
top:90,
child: InkWell(
onTap: () {
setState(() {
_menuShown = !_menuShown;
});
},
child: Image.asset(
'assets/images/girls.png',
height: 250,
),
),
),
Positioned(
child: FadeTransition(
opacity: opacityAnimation,
child: _DialogUI(),
),
right: 40.0,
top: 300.0,
),
],
),
);
}
}
class _DialogUI extends StatelessWidget {
_DialogUI();
final double padding = 8.0;
#override
Widget build(BuildContext context) {
return Center(
child: Material(
clipBehavior: Clip.antiAlias,
shape: _DialogShapeBorder(
borderRadius: BorderRadius.all(Radius.circular(padding)),
padding: padding),
elevation: 4.0,
child: Container(
margin: const EdgeInsets.all(10),
padding: EdgeInsets.all(padding).copyWith(bottom: padding * 2),
child: Center(
child: Text(
'Filler text is text that shares \nsome characteristics of a real written text, \n but is random or otherwise generated.\n It may be used to display a sample of fonts,\n generate text for testing, or to spoof an e-mail spam filter.'),
),
)),
);
}
}
class _DialogShapeBorder extends RoundedRectangleBorder {
_DialogShapeBorder({
#required this.padding,
side = BorderSide.none,
borderRadius = BorderRadius.zero,
}) : super(side: side, borderRadius: borderRadius);
final double padding;
#override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return Path()
..moveTo(rect.width - 18.0, rect.top)
..lineTo(rect.width - 20.0, rect.top - 36.0)
..lineTo(rect.width - 52.0, rect.top)
..addRRect(borderRadius.resolve(textDirection).toRRect(Rect.fromLTWH(
rect.left, rect.top, rect.width, rect.height - padding)));
}
}
Output