How to cliping container from center top - flutter

Hello everyone I want to clip container from center top. I tried with custom clipper but not get success. Anyone please help me how to draw container like below image.
My Code
ClipPath(
clipper: TriangleClipper(),
child: Container(
height: 120,
color: Colors.red,
),
),
class TriangleClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var firstControlPoint = Offset(size.width / 2.5, 50.0);
var firstEndPoint = Offset(size.width / 2, 10.0);
var secondControlPoint = Offset(size.width - (size.width / 2.5), 50);
var secondEndPoint = Offset(size.width, 50);
var path = Path()
..lineTo(0, 50)
..lineTo(0, 70)
..cubicTo(0, 70, 0, 50, 20, 50)
..quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstEndPoint.dx, firstEndPoint.dy)
..quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondEndPoint.dx, secondEndPoint.dy)
..lineTo(size.width - 20, 50)
..cubicTo(size.width - 20, 50, size.width, 50, size.width, 70)
..lineTo(size.width, size.height)
..lineTo(0.0, size.height)
..close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Output:

i think you were missing path.moveTo(0.0, size.height);
import 'package:flutter/material.dart';
class CardCliping extends StatelessWidget {
const CardCliping({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.deepPurple.shade300,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipPath(
clipper: TriangleClipper(),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.white)),
width: 130,
height: 40,
),
),
Container(
width: 400,
height: 100,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
border: Border.all(color: Colors.white, width: 0)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
GestureDetector(
onTap: () {},
child: Icon(
Icons.home_outlined,
color: Colors.deepPurpleAccent,
),
),
GestureDetector(
onTap: () {},
child: Icon(
Icons.person_outline_outlined,
color: Colors.deepPurpleAccent,
),
)
],
),
),
],
),
),
);
}
}
class TriangleClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final path = Path();
path.moveTo(0.0, size.height);
path.lineTo(size.width * .5, 0);
//we dont need this
// path.lineTo(size.width, size.height);
path.lineTo(size.width, size.height);
path.close();
return path;
}
#override
bool shouldReclip(TriangleClipper oldClipper) => false;
}

Related

How to use clip path with sliver app bar in flutter

Can anyone explain me how to change clip path of sliver app bar in flutter
class MyClipper extends CustomClipper<Path> {
#override Path getClip(Size size) {
final radius = 32.0;
final r = Offset.zero & size;
final r1 = Rect.fromCircle(center: r.bottomRight - Offset(radius, radius * 2), radius: radius);
final r2 = Rect.fromCircle(center: r.bottomLeft + Offset(radius, 0), radius: radius);
return Path()
..moveTo(r.topLeft.dx, r.topLeft.dy)
..lineTo(r.topRight.dx, r.topRight.dy)
..arcTo(r1, 0, pi / 2, false)
..arcTo(r2, -pi / 2, -pi / 2, false);
}
#override bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
Answer owner: pskink
You can use that, my design supporting auto resize clip path and working perfectly
import 'package:flutter/material.dart';
import 'package:unfpa/base/base_stateful_state.dart';
import 'package:unfpa/utils/constants.dart';
import 'package:unfpa/utils/custom_clip_path.dart';
import 'package:unfpa/utils/custom_clip_path_two.dart';
class TestWidget extends StatefulWidget {
TestWidget({Key key}) : super(key: key);
#override
_TestWidgetState createState() => _TestWidgetState();
}
class _TestWidgetState extends BaseStatefulState<TestWidget> {
final ScrollController _sliverScrollController = ScrollController();
ValueNotifier<bool> isPinned = ValueNotifier(false);
Size size;
#override
void initState() {
super.initState();
_sliverScrollController.addListener(() {
if (!isPinned.value &&
_sliverScrollController.hasClients &&
_sliverScrollController.offset > kToolbarHeight) {
isPinned.value = true;
} else if (isPinned.value &&
_sliverScrollController.hasClients &&
_sliverScrollController.offset < kToolbarHeight) {
isPinned.value = false;
}
});
}
#override
Widget build(BuildContext context) {
size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.white,
body: CustomScrollView(
controller: _sliverScrollController,
slivers: <Widget>[
ValueListenableBuilder(
valueListenable: isPinned,
builder: (context, value, child) {
return SliverAppBar(
elevation: 0,
backgroundColor: Colors.red,
leading: IconButton(
iconSize: 48,
color: Colors.white,
icon: Icon(Icons.close),
onPressed: () => Navigator.of(context).pop()),
primary: true,
pinned: true,
stretch: true,
title: Visibility(
visible: value,
child: Text(
"Sliver AppBar Title",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 22.0,
color: Colors.white,
),
),
),
titleSpacing: 0,
);
}),
SliverList(
delegate: SliverChildListDelegate([
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
transform: Matrix4.translationValues(0.0, -2.0, 0.0),
alignment: Alignment.center,
child: ClipPath(
clipper: ClipPathClass(),
child: Container(
padding: EdgeInsets.only(bottom:20),
width: size.width,
color: Colors.yellow,
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 25),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: kToolbarTopMargin),
Text(
"Expanded Sliver title",
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
),
),
SizedBox(
height: 5,
),
Text(
"Expanded sliver description",
style: TextStyle(
fontSize: 17,
color: Colors.white,
height: 1.3,
fontWeight: FontWeight.w700,
),
)
],
),
),
),
),
),
],
)
])),
],
));
}
}
CustomClipPathClass
import 'package:flutter/material.dart';
class ClipPathClass extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height - 30);
var firstControlPoint = Offset(size.width / 4, size.height);
var firstPoint = Offset(size.width / 2, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstPoint.dx, firstPoint.dy);
var secondControlPoint = Offset(size.width - (size.width / 4), size.height);
var secondPoint = Offset(size.width, size.height - 30);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondPoint.dx, secondPoint.dy);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

Flutter add shadow in Custom painter

I am following some tutorial and fine a very good navbar but issue is when i replace it in my app i need to add shadow.
Here is the code
class BottomNavBarV2 extends StatefulWidget {
#override
_BottomNavBarV2State createState() => _BottomNavBarV2State();
}
class _BottomNavBarV2State extends State<BottomNavBarV2> {
int currentIndex = 0;
setBottomBarIndex(index) {
setState(() {
currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.white.withAlpha(55),
body: Stack(
children: [
Positioned(
bottom: 0,
left: 0,
child: Container(
width: size.width,
height: 80,
child: Stack(
overflow: Overflow.visible,
children: [
CustomPaint(
size: Size(size.width, 80),
painter: BNBCustomPainter(),
),
Center(
heightFactor: 0.6,
child: FloatingActionButton(backgroundColor: Colors.orange, child: Icon(Icons.shopping_basket), elevation: 0.1, onPressed: () {}),
),
Container(
width: size.width,
height: 80,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
icon: Icon(
Icons.home,
color: currentIndex == 0 ? Colors.orange : Colors.grey.shade400,
),
onPressed: () {
setBottomBarIndex(0);
},
splashColor: Colors.white,
),
IconButton(
icon: Icon(
Icons.restaurant_menu,
color: currentIndex == 1 ? Colors.orange : Colors.grey.shade400,
),
onPressed: () {
setBottomBarIndex(1);
}),
Container(
width: size.width * 0.20,
),
IconButton(
icon: Icon(
Icons.bookmark,
color: currentIndex == 2 ? Colors.orange : Colors.grey.shade400,
),
onPressed: () {
setBottomBarIndex(2);
}),
IconButton(
icon: Icon(
Icons.notifications,
color: currentIndex == 3 ? Colors.orange : Colors.grey.shade400,
),
onPressed: () {
setBottomBarIndex(3);
}),
],
),
)
],
),
),
)
],
),
);
}
}
class BNBCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = new Paint()
..color = Colors.white
..style = PaintingStyle.fill;
Path path = Path();
path.moveTo(0, 20); // Start
path.quadraticBezierTo(size.width * 0.20, 0, size.width * 0.35, 0);
path.quadraticBezierTo(size.width * 0.40, 0, size.width * 0.40, 20);
path.arcToPoint(Offset(size.width * 0.60, 20), radius: Radius.circular(20.0), clockwise: false);
path.quadraticBezierTo(size.width * 0.60, 0, size.width * 0.65, 0);
path.quadraticBezierTo(size.width * 0.80, 0, size.width, 20);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 20);
canvas.drawShadow(path, Colors.black, 5, true);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
Screen shot
[
I need to add shadow in this curved navbar. Because body and navbar both is white and navbar curved is not much visible. Need to add little shadow so can see curves easily
You can use the below code to gain the custom shadow for your widget. Just wrap your widget with the below container.
return Container(
margin: EdgeInsets.only(left: 20, top: 50, right: 20, bottom: 50),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 8,
blurRadius: 10,
offset: Offset(0, 5), // changes position of shadow
),
],
),
)

How to create curve in container in flutter

How to create curve in container like this
If you need to create a curve for the container that the profile picture lives on top of, your best bet would be to use a ClipPath with a custom clipper.
Something like this would do the trick:
ClipPath(
clipper: CurveClipper(),
child: Container(
color: Colors.red,
height: 200.0,
),
);
Our custom CurveClipper requires us to draw a path that includes a bézier curve, to get that curve shape at the bottom of our container:
class CurveClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
int curveHeight = 40;
Offset controlPoint = Offset(size.width / 2, size.height + curveHeight);
Offset endPoint = Offset(size.width, size.height - curveHeight);
Path path = Path()
..lineTo(0, size.height - curveHeight)
..quadraticBezierTo(controlPoint.dx, controlPoint.dy, endPoint.dx, endPoint.dy)
..lineTo(size.width, 0)
..close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
It's rounded Appbar actually in this picture. To achive this:
AppBar(
title: Text('Anything'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(30),
),
),
),
If you want container with this shape:
Container(
height: 200.0,
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.vertical(
bottom: Radius.elliptical(
MediaQuery.of(context).size.width, 100.0)),
),
),
I used CustomPainter to draw the required container and placed it at the bottom of the stack. The rest of the widgets can be aligned on top as required. Complete the rest of the screen by populating the Column widget.
Image of the output is as shown: Output Image for the design
Code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ProfileScreen(),
);
}
}
// class to draw the profile screen
class ProfileScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: const Color(0xffea5d49),
leading: Icon(
Icons.menu,
color: Colors.white,
),
),
body: Stack(
alignment: Alignment.center,
children: [
CustomPaint(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
),
painter: HeaderCurvedContainer(),
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
'Profile',
style: TextStyle(
fontSize: 35.0,
letterSpacing: 1.5,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
),
Container(
width: MediaQuery.of(context).size.width / 2,
height: MediaQuery.of(context).size.width / 2,
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
// image: DecorationImage(
// image: AssetImage(null),
// fit: BoxFit.cover,
// ),
),
),
],
),
],
),
),
);
}
}
// CustomPainter class to for the header curved-container
class HeaderCurvedContainer extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()..color = const Color(0xffea5d49);
Path path = Path()
..relativeLineTo(0, 150)
..quadraticBezierTo(size.width / 2, 250.0, size.width, 150)
..relativeLineTo(0, -150)
..close();
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}

How to create one side skew container in flutter

I'm new to Flutter. How do I create the shape marked here? I tried. Below is the code.
Positioned(
top: 30.0,
left: 15.0,
width: 50.0,
height: 20.0,
child: Container(
decoration: BoxDecoration(
color: Colors.pink,
shape: BoxShape.rectangle
),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0,horizontal: 8.0),
child: Text('අලුත්ම පුවත',style: TextStyle(color: Colors.white, fontSize: 10.0,fontWeight: FontWeight.bold)),
),
),
complete code
You can use clipPath to achieve desire output.
Following code help you more to understand.
class DeleteWidget extends StatefulWidget {
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ClipPath(
clipper: SkewCut(),
child: Container(
color: Colors.red,
width: 200,
height: 50,
child: Center(child: Text("Hello World")),
),
),
),
);
}
}
class SkewCut extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final path = Path();
path.lineTo(size.width, 0);
path.lineTo(size.width - 20, size.height);
path.lineTo(0, size.height);
path.close();
return path;
}
#override
bool shouldReclip(SkewCut oldClipper) => false;
}

Flutter: How to make telegram type bubble in chat message

Current output:
Expected output:
Code:
Align(
alignment: Alignment.topRight,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
margin: EdgeInsets.only(right: 12, top: 8),
decoration: BoxDecoration(
color: Color(0xFF486993),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Text("This is my message"),
),
)
Here is what exactly needed to create neat speech bubble in flutter.
first create a custom painter class that extends Painter class
class CustomChatBubble extends CustomPainter {
CustomChatBubble({this.color, #required this.isOwn});
final Color color;
final bool isOwn;
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color ?? Colors.blue;
Path paintBubbleTail() {
Path path;
if (!isOwn) {
path = Path()
..moveTo(5, size.height - 5)
..quadraticBezierTo(-5, size.height, -16, size.height - 4)
..quadraticBezierTo(-5, size.height - 5, 0, size.height - 17);
}
if (isOwn) {
path = Path()
..moveTo(size.width - 6, size.height - 4)
..quadraticBezierTo(
size.width + 5, size.height, size.width + 16, size.height - 4)
..quadraticBezierTo(
size.width + 5, size.height - 5, size.width, size.height - 17);
}
return path;
}
final RRect bubbleBody = RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(16));
final Path bubbleTail = paintBubbleTail();
canvas.drawRRect(bubbleBody, paint);
canvas.drawPath(bubbleTail, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
then use it in your chat screen. please note that this screen for only demo purpose so you can modify it according to your needs.
class ChatSampleWidget extends StatefulWidget {
#override
_ChatSampleWidgetState createState() => _ChatSampleWidgetState();
}
class _ChatSampleWidgetState extends State<ChatSampleWidget> {
TextEditingController _editingController = TextEditingController();
FocusNode _focusNode = FocusNode();
final TextStyle textStyle = TextStyle(color: Colors.white);
#override
void initState() {
super.initState();
}
#override
dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Chatter'),
),
body: SafeArea(
child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
CustomPaint(
painter: CustomChatBubble(isOwn: false),
child: Container(
padding: EdgeInsets.all(8),
child: Text(
'Message from someone else \n Says sometihngs',
style: textStyle,
))),
],
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
CustomPaint(
painter:
CustomChatBubble(color: Colors.grey, isOwn: false),
child: Container(
padding: EdgeInsets.all(10),
child: FlutterLogo())),
],
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CustomPaint(
painter:
CustomChatBubble(color: Colors.green, isOwn: true),
child: Container(
padding: EdgeInsets.all(8),
child: Text(
'Message from me',
style: textStyle,
))),
],
)
],
),
),
Positioned(
bottom: 0,
child: Container(
padding: EdgeInsets.all(8),
width: MediaQuery.of(context).size.width,
color: Colors.grey.withOpacity(0.1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Flexible(
child: TextField(
controller: _editingController,
focusNode: _focusNode,
decoration:
InputDecoration(hintText: 'Say something...'),
),
),
IconButton(
icon: Icon(
Icons.send,
size: 30,
),
onPressed: () {
print(_editingController.text);
})
],
),
))
],
),
),
);
}
}
this is how it looks;
Here you are:
import 'package:flutter/material.dart';
void main() => runApp(
MyApp()
);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Padding(
padding: EdgeInsets.all(7),
child: Align(
alignment: Alignment.centerRight,
child: Stack(
children: [
Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
decoration: BoxDecoration(
color: Color(0xFF486993),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: 'This is telegram message ',
style: TextStyle(
color: Colors.white,
fontSize: 14.0
),
),
TextSpan(
text: '3:16 PM',
style: TextStyle(
color: Colors.grey,
fontSize: 12.0,
fontStyle: FontStyle.italic
),
),
],
),
),
Icon(Icons.check, color: Color(0xFF7ABAF4), size: 16,)
]
),
),
Positioned(
bottom: 0,
right: 0,
child: CustomPaint(
painter: ChatBubbleTriangle(),
)
)
]
)
),
),
);
}
}
class ChatBubbleTriangle extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()..color = Color(0xFF486993);
var path = Path();
path.lineTo(-15, 0);
path.lineTo(0, -15);
path.lineTo(0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
You will have to change paint method, because now it's just a triangle.
Otherwise, it looks as you requested.
Trying to recreate Telegram layout myself I came up with this to make the shape;
enum _TailDirection { right, left }
class ChatBubblePainter extends CustomPainter {
ChatBubblePainter({this.color, this.isSentByMe});
final Color color;
final bool isSentByMe;
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
Path paintBubbleTail(_TailDirection direction) {
double startingPoint;
double point;
double endPoint;
double curvePoint;
if (direction == _TailDirection.right) {
startingPoint = size.width - 5;
point = size.width + 10;
endPoint = size.width + 3;
curvePoint = size.width;
}
if (direction == _TailDirection.left) {
startingPoint = 5;
point = -10;
endPoint = -3;
curvePoint = 0;
}
return Path()
..moveTo(startingPoint, size.height)
..lineTo(point, size.height)
..quadraticBezierTo(endPoint, size.height, curvePoint, size.height - 10);
}
final RRect bubbleBody = RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(5.0));
final Path bubbleTail = isSentByMe
? paintBubbleTail(_TailDirection.right)
: paintBubbleTail(_TailDirection.left);
canvas.drawRRect(bubbleBody, paint);
canvas.drawPath(bubbleTail, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}