How BeveledRectangleBorder for TextField in flutter - flutter

I have TextField i need to change the border Corners Cut, I have try to do with wrap TextField on Container and apply BeveledRectangleBorder but is not proper.
Please suggest me how can do this.

Update
After searching a little i've found the source code of that design you shared with me. They have build a custom input border (CutCornersBorder) for that particular style. You can use that file and add that to your theme to get that look of your TextField without adding any extra code.
CutCornersBorder
return MaterialApp(
home: HomePage(),
theme: ThemeData(
inputDecorationTheme: InputDecorationTheme(border: CutCornersBorder()),
),
);
Full Preview
OLD
You can do it by creating your own custom painter implementation.
FlatCorneredBackgroundPainter
class FlatCorneredBackgroundPainter extends CustomPainter {
double radius, strokeWidth;
Color strokeColor;
FlatCorneredBackgroundPainter(
{this.radius = 10, this.strokeWidth = 4, this.strokeColor = Colors.blue});
#override
void paint(Canvas canvas, Size size) {
double w = size.width;
double h = size.height;
Paint paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..color = strokeColor;
Path path = Path()
..addPolygon([
Offset(radius, 0),
Offset(w - radius, 0),
Offset(w, radius),
Offset(w, h - radius),
Offset(w - radius, h),
Offset(radius, h),
Offset(0, h - radius),
Offset(0, radius),
], true);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
Usage
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: CustomPaint(
painter: FlatCorneredBackgroundPainter(radius: 10.0, strokeColor: Colors.red, strokeWidth: 2),
child: Container(
width: 300,
height: 70,
padding: const EdgeInsets.all(8.0),
child: TextField(),
),
),
),
);
}
}

Related

How to make art work fill a custom painted border shape in flutter

I made a custom shape of a crooked square for music artwork images, now I'm trying to make the image fill it completely whilst not leaking out of it.
I tried using a stack, but it is bugging the painted square and the image still would leak and not fill it completely.
SizedBox(
width: 50,
height: 50,
child: CustomPaint(
painter: ImperfectRectangleBorder(strokeColor: Colors.white),
child: QueryArtworkWidget(//from on_audio_query package
artworkBorder: BorderRadius.zero,
artworkFit: BoxFit.fill,
id: item.data![index].id,
type: ArtworkType.AUDIO,
),
),
),
class ImperfectRectangleBorder extends CustomPainter {
final Color strokeColor;
ImperfectRectangleBorder({this.strokeColor = Colors.white});
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = strokeColor
..strokeWidth = 4.0
..style = PaintingStyle.stroke;
var path = Path();
path.moveTo(0, -5);
path.lineTo(size.width * (0.2), size.height + 10);
path.lineTo(size.width, size.height - 5);
path.lineTo(size.height * (0.8), -1);
path.close();
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}

flutter: custom shape as text background

I need to achieve this in flutter:
I tried making a Row and setting a background to the Text to handle the ractangle, then a ClipPath to make the triangle. The problem with this is that the edge is not precise (you can see a thin line between the rectangle and the triangle in the image below), also the ClipPath has fixed size so if I want to change the text size at some point I'll have to fine-tune the triangle again.
here's my code:
class TriangleClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final path = Path();
path.lineTo(0.0, size.height);
path.lineTo(size.width / 3, size.height);
path.close();
return path;
}
#override
bool shouldReclip(TriangleClipper oldClipper) => false;
}
Row(
children: [
Container(
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
"a label",
),
),
),
ClipPath(
clipper: TriangleClipper(),
child: Container(
color: Colors.orange,
height: 23,
width: 20,
),
)
],
)
I though using double.infinity instead of fixed size in ClipPath's child would solve it but doing that makes the triangle disappear (probably it becomes too big that I can't see it or goes behind something).
What is the correct way to approache this problem? I guess I could draw the trapezoid using a ClipPath, but how to make it so the width of it adapts to the lenght of the Text?
One way to achieve this is like so.
class TriangleClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final w = size.width;
final h = size.height;
final triangleWidth = 10;
final path = Path();
path.lineTo(0, 0);
path.lineTo(0, h);
path.lineTo(w, h);
path.lineTo(w - triangleWidth, 0);
path.close();
return path;
}
#override
bool shouldReclip(TriangleClipper oldClipper) => false;
}
and use it like so.
ClipPath(
clipper: TriangleClipper(),
child: Container(
padding: EdgeInsets.fromLTRB(4, 4, 14, 4), // 4 + triangleWidth for right padding
color: Colors.orange,
child: Text('A label'),
),
),
You can try the following code:
import 'dart:ui' as ui;
child: CustomPaint(
size: Size(WIDTH,(WIDTH*0.625).toDouble()), //You can Replace [WIDTH] with your desired width for Custom Paint and height will be calculated automatically
painter: RPSCustomPainter(),
),
class RPSCustomPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
Paint paint_0 = new Paint()
..color = Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.fill
..strokeWidth = 1;
paint_0.shader = ui.Gradient.linear(Offset(size.width*0.29,size.height*0.28),Offset(size.width*0.29,size.height*0.28),[Color(0xff7c1010),Color(0xffffffff)],[0.00,1.00]);
Path path_0 = Path();
path_0.moveTo(size.width*0.2937500,size.height*0.2780000);
canvas.drawPath(path_0, paint_0);
Paint paint_1 = new Paint()
..color = Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.fill
..strokeWidth = 1;
Path path_1 = Path();
path_1.moveTo(size.width*0.3750000,size.height*0.4000000);
path_1.lineTo(size.width*0.5000000,size.height*0.4000000);
path_1.lineTo(size.width*0.5375000,size.height*0.5000000);
path_1.lineTo(size.width*0.3750000,size.height*0.5000000);
path_1.lineTo(size.width*0.3750000,size.height*0.4000000);
path_1.close();
canvas.drawPath(path_1, paint_1);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
You can try it by yourself: https://shapemaker.web.app/#/

GestureDetector on painted triangles in circle

I'm trying to handle taps for three painted "quartercirlces" using the CustomPaint widget. I've tried adding GestureDetectors around the QuarterCirclePainter class. Even tried using using a GestureRecognizer for the TextSpan without any success. Tried wrapping it in containers wrapped in gestureDetectors. Looked at similar posts about adding GestureDetectors around the CustomPaint, but none of them seems to work in this case.
How can this be achieved?
class CategoryCircle extends StatelessWidget {
final Color color;
final double startAngle;
final String category;
final Offset textOffset;
CategoryCircle({this.color, this.startAngle, this.category, this.textOffset});
Widget build(BuildContext context) {
FocusScope.of(context).nextFocus();
return FractionallySizedBox(
widthFactor: 1,
heightFactor: 1,
child: Center(
child: CustomPaint(
painter: QuarterCirclePainter(
context: context,
color: color,
startAngle: startAngle,
sweepAngle: math.pi * 2 / 3,
text: category,
textOffset: textOffset)),
),
);
}
}
class QuarterCirclePainter extends CustomPainter {
final BuildContext context;
final Color color;
final double startAngle;
final double sweepAngle;
final String text;
final Offset textOffset;
const QuarterCirclePainter(
{this.context,
this.color,
this.startAngle,
this.sweepAngle,
this.text,
this.textOffset});
#override
void paint(Canvas canvas, Size size) {
Offset center = Offset(size.width / 2, size.height / 2);
Rect rect = Rect.fromCircle(center: center, radius: 130);
Path path = Path()
// set the "current point"
..moveTo(center.dx, center.dy)
..arcTo(rect, startAngle, (math.pi * 2) / 3, false);
canvas.drawPath(path, Paint()..color = color);
TextSpan span = new TextSpan(
style: GoogleFonts.overpass(
textStyle: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
text: text);
TextPainter tp = new TextPainter(
text: span,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr);
tp.layout();
tp.paint(canvas, textOffset);
}
#override
bool shouldRepaint(QuarterCirclePainter oldDelegate) {
return false;
}
}
I made a CustomClipper with what you did in the QuarterCirclePainter, it looks like this:
class QuaterCircleClipper extends CustomClipper<Path>{
double startAngle, sweepAngle;
QuaterCircleClipper({#required this.startAngle, #required this.sweepAngle});
#override
Path getClip(Size size){
Offset center = Offset(size.width / 2, size.height / 2);
Rect rect = Rect.fromCircle(center: center, radius: 130);
Path path = Path()
// set the "current point"
..moveTo(center.dx, center.dy)
..arcTo(rect, startAngle, (math.pi * 2) / 3, false);
return path;
}
#override
bool shouldReclip(oldCliper) => false;
}
And used a ClipPath with the above CustomClipper as clipper to wrap a GestureDetector which has a blue Container as its child
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: AspectRatio(
aspectRatio: 1,
child: ClipPath(
clipper: QuaterCircleClipper(startAngle: 0, sweepAngle: 120),
child: GestureDetector(
onTap: (){showDialog(context: context, builder: (_) => AlertDialog(content: Text("Tap Detected"),));},
child: Container(
color: Colors.blueAccent,
)
),
),
)
),

How to implement a Chat bubble shaped widget in flutter

I want to design a widget of shape of a chat bubble where one corner is pinned and its height should adjust to the lines of the text? For now I'm using ClipRRect widget with some borderRadius. But I want one corner pinned. Any suggestions ?
UPDATE
I know this can be done using a stack but I'm looking for a better solution since I have to use it many times in a single view and using many stacks might affect the performs. ( correct me here if I'm wrong )
For someone who want this get done with library. You can add bubble: ^1.1.9+1 (Take latest) package from pub.dev and wrap your message with Bubble.
Bubble(
style: right ? styleMe : styleSomebody,
//Your message content child here...
)
Here right is boolean which tells the bubble is at right or left, Write your logic for that and add the style properties styleMe and styleSomebody inside your widget as shown below. Change style according to your theme.
double pixelRatio = MediaQuery.of(context).devicePixelRatio;
double px = 1 / pixelRatio;
BubbleStyle styleSomebody = BubbleStyle(
nip: BubbleNip.leftTop,
color: Colors.white,
elevation: 1 * px,
margin: BubbleEdges.only(top: 8.0, right: 50.0),
alignment: Alignment.topLeft,
);
BubbleStyle styleMe = BubbleStyle(
nip: BubbleNip.rightTop,
color: Colors.grey,
elevation: 1 * px,
margin: BubbleEdges.only(top: 8.0, left: 50.0),
alignment: Alignment.topRight,
);
Hi im also searching for a chat bubble shaped widget finally i made one.
I have made this in custom Painter and i'm not good at it.
import 'package:flutter/material.dart';
class ChatBubble extends CustomPainter {
final Color color;
final Alignment alignment;
ChatBubble({
#required this.color,
this.alignment,
});
var _radius = 10.0;
var _x = 10.0;
#override
void paint(Canvas canvas, Size size) {
if (alignment == Alignment.topRight) {
canvas.drawRRect(
RRect.fromLTRBAndCorners(
0,
0,
size.width - 8,
size.height,
bottomLeft: Radius.circular(_radius),
topRight: Radius.circular(_radius),
topLeft: Radius.circular(_radius),
),
Paint()
..color = this.color
..style = PaintingStyle.fill);
var path = new Path();
path.moveTo(size.width - _x, size.height - 20);
path.lineTo(size.width - _x, size.height);
path.lineTo(size.width, size.height);
canvas.clipPath(path);
canvas.drawRRect(
RRect.fromLTRBAndCorners(
size.width - _x,
0.0,
size.width,
size.height,
topRight: Radius.circular(_radius),
),
Paint()
..color = this.color
..style = PaintingStyle.fill);
} else {
canvas.drawRRect(
RRect.fromLTRBAndCorners(
_x,
0,
size.width,
size.height,
bottomRight: Radius.circular(_radius),
topRight: Radius.circular(_radius),
topLeft: Radius.circular(_radius),
),
Paint()
..color = this.color
..style = PaintingStyle.fill);
var path = new Path();
path.moveTo(0, size.height);
path.lineTo(_x, size.height);
path.lineTo(_x, size.height-20);
canvas.clipPath(path);
canvas.drawRRect(
RRect.fromLTRBAndCorners(
0,
0.0,
_x,
size.height,
topRight: Radius.circular(_radius),
),
Paint()
..color = this.color
..style = PaintingStyle.fill);
}
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
copy and paste the above code and paste in your project
Align(
alignment: alignment, //Change this to Alignment.topRight or Alignment.topLeft
child: CustomPaint(
painter: ChatBubble(color: Colors.blue, alignment: alignment),
child: Container(
margin: EdgeInsets.all(10),
child: Stack(
children: <Widget>[
TextView("Hello World"),
],
),
),
),
)
paste this code where you have to show chatBubble Widget.
And i have also upload this code in bitbucket ChatBubble Widget Please be free if you have anything to contribute.
Sorry I am not able to show you the code for it but I can present an idea that might work if you implement it correctly. Suppose the Widget you made with ClipRect is called MyChatBubbleRect. Now, make another widget that draws a triangle using CustomPainter, let's call it MyChatBubbleTriangle, of course fill it with same color as the chat bubble but you can use a different color initially for debugging. Now that we have two widgets we can stack 'em together on top of each other and using Positioned widget over the MyChatBubbleTriangle. Something like this:
Stack(
children : [
MyChatBubbleRect(), // Maybe decrease the width a bit
Positioned(
top: 0,
right: 0,
child: MyChatBubbleTriangle()
)
]
)
This is just an idea I think you can pursue. Sorry couldn't provide the proper source code.
Chat Body
DecoratedBox(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.0),
),
child: Text("your message goes here"),
);
Make a custom Triangle
class ChatBubbleTriangle extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()..color = Colors.blue;
var path = Path();
path.lineTo(-10, 0);
path.lineTo(0, 10);
path.lineTo(10, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Use both of them within a stack wrapping ChatBubbleTriangle with Positioned() widget

How to create a dotted border around a box in flutter?

I am building a list of boxes layouts in my app using flutter. I want dotted border around the box. I have used card widget to create the boxes. But, how can I get dotted border around the boxes?
EDIT
I have added this as a package in pub.
Now, all you need to do is
DottedBorder(
color: Colors.black,
gap: 3,
strokeWidth: 1,
child: FlutterLogo(size: 148),
)
Working Solution [Outdated]
Like tomerpacific said in this answer, Flutter does not have a default implementation for dashed border at the moment.
I worked for some time yesterday and was able to come up with a solution using CustomPainter. Hope this helps someone.
Add the DashedRect to your container, like so
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
height: 400,
width: 300,
color: Colors.black12,
child: DashedRect(color: Colors.red, strokeWidth: 2.0, gap: 3.0,),
),
),
);
}
}
DashedRect.dart
import 'package:flutter/material.dart';
import 'dart:math' as math;
class DashedRect extends StatelessWidget {
final Color color;
final double strokeWidth;
final double gap;
DashedRect(
{this.color = Colors.black, this.strokeWidth = 1.0, this.gap = 5.0});
#override
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.all(strokeWidth / 2),
child: CustomPaint(
painter:
DashRectPainter(color: color, strokeWidth: strokeWidth, gap: gap),
),
),
);
}
}
class DashRectPainter extends CustomPainter {
double strokeWidth;
Color color;
double gap;
DashRectPainter(
{this.strokeWidth = 5.0, this.color = Colors.red, this.gap = 5.0});
#override
void paint(Canvas canvas, Size size) {
Paint dashedPaint = Paint()
..color = color
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke;
double x = size.width;
double y = size.height;
Path _topPath = getDashedPath(
a: math.Point(0, 0),
b: math.Point(x, 0),
gap: gap,
);
Path _rightPath = getDashedPath(
a: math.Point(x, 0),
b: math.Point(x, y),
gap: gap,
);
Path _bottomPath = getDashedPath(
a: math.Point(0, y),
b: math.Point(x, y),
gap: gap,
);
Path _leftPath = getDashedPath(
a: math.Point(0, 0),
b: math.Point(0.001, y),
gap: gap,
);
canvas.drawPath(_topPath, dashedPaint);
canvas.drawPath(_rightPath, dashedPaint);
canvas.drawPath(_bottomPath, dashedPaint);
canvas.drawPath(_leftPath, dashedPaint);
}
Path getDashedPath({
#required math.Point<double> a,
#required math.Point<double> b,
#required gap,
}) {
Size size = Size(b.x - a.x, b.y - a.y);
Path path = Path();
path.moveTo(a.x, a.y);
bool shouldDraw = true;
math.Point currentPoint = math.Point(a.x, a.y);
num radians = math.atan(size.height / size.width);
num dx = math.cos(radians) * gap < 0
? math.cos(radians) * gap * -1
: math.cos(radians) * gap;
num dy = math.sin(radians) * gap < 0
? math.sin(radians) * gap * -1
: math.sin(radians) * gap;
while (currentPoint.x <= b.x && currentPoint.y <= b.y) {
shouldDraw
? path.lineTo(currentPoint.x, currentPoint.y)
: path.moveTo(currentPoint.x, currentPoint.y);
shouldDraw = !shouldDraw;
currentPoint = math.Point(
currentPoint.x + dx,
currentPoint.y + dy,
);
}
return path;
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
I do not expect this to fit in with all use cases and there is a lot of room for customization and improvement. Comment if you find any bugs.
You can use dotted_border Flutter package
return DottedBorder(
borderType: BorderType.RRect,
radius: Radius.circular(20),
dashPattern: [10, 10],
color: Colors.grey,
strokeWidth: 2,
child: Card(
color: Colors.amber,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Center(child: Text("hi")),
)
There is an one plugin for draw dotted border around widgets
https://pub.dev/packages/dotted_border
Using this plugin you can draw dotted or dashed border
//1. Install the plugin by add dependencies in pubspace.yaml
dotted_border: ^1.0.6
Add below code for show border
DottedBorder(
color: Colors.black,
strokeWidth: 1,
child: FlutterLogo(size: 148),
)
BorderStyle.none can be useful if you wanna apply some animation or remove\add border function onTap(like a lighting border) event or similar.