How to create one side skew container in flutter - 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;
}

Related

How to create the following shape in flutter?

I wan to create above shape in flutter. I was using clipPath for getting the sides right but i couldn't get the rounded corners.
You must use for this shape flutter_custom_clippers package from here.
Add this dependency in your pubspec.yaml file
Try below code hope its help to you
Import package in your file
import 'package:flutter_custom_clippers/flutter_custom_clippers.dart';
Your Widget:
ClipPath(
clipper: RoundedDiagonalPathClipper(),
child: Container(
height: 320,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(
50.0,
),
),
color: Colors.grey[300],
),
child: Center(
child: Text("Your Shape"),
),
),
),
Your result screen->
You can do this with CustomClipper
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Rounded corner'),
),
body: Container(
decoration: BoxDecoration(
color: Color(0xff240046), borderRadius: BorderRadius.circular(15)),
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 18),
margin: EdgeInsets.symmetric(vertical: 8),
child: ClipPath(
clipper: CustomRectClipper(),
child: Container(
height: 500,
width: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(50.0)),
color: Colors.grey,
),
child: Center(child: Text("RoundedDiagonalPathClipper()")),
),
),
),
);
}
}
class CustomRectClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path path = new Path()
..lineTo(0.0, size.height)
..lineTo(size.width, size.height)
..lineTo(size.width, 0.0)
..quadraticBezierTo(size.width-50, 0.0, size.width - 60.0, -5.0)
..lineTo(40.0, 150.0) // here you adjust the value as much as you nee
..quadraticBezierTo(0.0, 180.0, 0.0, 220.0);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
Output:

How to cliping container from center top

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;
}

how to overlap items on Appbar flutter

I want to achieve have a round icon for the profile image like in this example:
But is not working for me, this is what I achieved so far:
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: _AppBarProfileClipper(childHeight),
child: Container(
padding: const EdgeInsets.only(top: 48.0),
color: TheBaseColors.lightBlue,
height: height,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
leading,
FlatButton(
onPressed: null,
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18.0,
color: Colors.white,
),
),
),
trailing,
],
),
),
),
Positioned(
bottom: childHeight / 2, //50
left: 0,
right: 0,
child: Align(
alignment: Alignment.bottomCenter,
child: child,
),
),
],
);
}
}
All the parameters are represented in the constructor and used in the code. But I cant figure out how to make that nice effect with the rounded icon.
Someone knows why is not working?
You can achieve given example like this:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final double appBarHeight = 100.0;
final double spaceAroundRoundButton = 4.0;
final double roundedButtonSize = 64.0;
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return SafeArea(
child: Stack(
children: <Widget>[
Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize:
Size(MediaQuery.of(context).size.width, appBarHeight),
child: ClipPath(
clipper: BottomClipper(),
child: Container(
alignment: Alignment.topLeft,
height: appBarHeight,
color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
),
onPressed: () {}),
Text(
'User Profile',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {})
],
),
),
)),
body: Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(
top:
roundedButtonSize * 0.75 + spaceAroundRoundButton + 16.0),
child: Text('Body'),
),
),
Positioned(
child: Container(
padding: EdgeInsets.all(spaceAroundRoundButton),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: RawMaterialButton(
elevation: 0,
constraints: BoxConstraints.tightFor(
width: roundedButtonSize, height: roundedButtonSize),
shape: StadiumBorder(
side: BorderSide(width: 4, color: Colors.grey)),
child: Icon(Icons.person),
onPressed: () {},
fillColor: Colors.white,
),
),
left: (size.width / 2) -
(roundedButtonSize / 2) -
spaceAroundRoundButton,
top: appBarHeight -
(roundedButtonSize * 0.25) -
spaceAroundRoundButton,
)
],
),
);
}
}
class BottomClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height * 0.75);
var firstControlPoint = Offset(size.width * 0.25, size.height);
var firstEndPoint = Offset(size.width * 0.5, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstEndPoint.dx, firstEndPoint.dy);
var secondControlPoint = Offset(size.width * 0.75, size.height);
var secondEndPoint = Offset(size.width, size.height * 0.75);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondEndPoint.dx, secondEndPoint.dy);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Screenshot:

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;
}

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;
}
}