How to paint a location icon in flutter? - flutter

I am trying to paint a icon with green color. I am using custom painter class.
Sample code:
import 'dart:ui';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
double x = 0.0;
double y = 0.0;
List<Offset> mark = [];
void updatePosition(TapDownDetails details) {
x = details.localPosition.dx;
y = details.localPosition.dy;
setState(() {
mark.add(Offset(x, y));
print("mark:$mark");
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GestureDetector(
onTapDown: updatePosition,
child: RepaintBoundary(
child: Container(
margin: const EdgeInsets.only(left: 8, right: 8),
height: 300,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
image: const DecorationImage(
image: AssetImage(
'assets/dark.jpg',
),
fit: BoxFit.cover)),
child: CustomPaint(
painter: MyCustomPainter(mark),
),
)),
),
),
);
}
}
class MyCustomPainter extends CustomPainter {
final List<Offset> marks;
const MyCustomPainter(this.marks);
#override
void paint(Canvas canvas, Size size) async {
Paint paint = Paint()
..color = Colors.green
..strokeCap = StrokeCap.round
..strokeWidth = 15.0;
canvas.drawPoints(PointMode.points, marks, paint);
}
#override
bool shouldRepaint(MyCustomPainter oldDelegate) {
return true;
}
}
It's helped me to draw a points list. How can I draw a list of location icon instead of green points?

Related

flutter container with curve border

I want this type container with curve border, please check attach images
best solution of answer
I am Using ShapeBorder with paint.
class CustomShape extends ShapeBorder {
#override
EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
#override
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
return getInnerPath(rect);
}
#override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
final double curveX = rect.width / 10;
Path rectPath = Path()
..addRRect(RRect.fromRectAndRadius(rect, const Radius.circular(24)));
Path curvePath = Path()
..moveTo(rect.center.dx - curveX, rect.top)
..quadraticBezierTo(
rect.center.dx,
rect.center.dy - curveX, //middle curve control
rect.center.dx + curveX,
rect.top,
);
return Path.combine(PathOperation.xor, rectPath, curvePath);
}
#override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
canvas.drawPath(
getOuterPath(rect),
Paint()
..color = Colors.red
..style = PaintingStyle.stroke);
}
#override
ShapeBorder scale(double t) => this;
}
And use
child: Container(
height: 200,
width: 500,
decoration: ShapeDecoration(
shape: CustomShape(),
),
),
Use quadraticBezierTo value to control the curve
I am pretty sure you will find something that will work here:
Flutter draw container with a curve in the center
Hope it helps.
Here is your Clip Code... and also use Shape Maker to design such layout and you will get clip code
Your Clip Container with border
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
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: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
#override
Widget build(BuildContext context) {
return Center(
child: CustomPaint(
painter: BorderPainter(),
child: Container(
height: 200,
width: 400,
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Pakistan'),
Spacer(),
Text('VS'),
Spacer(),
Text('India'),
],
),
)
)
),
),
);
}
}
Clipping Code of Container
class BorderPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2
..color = Colors.pink;
Path path0 = Path();
path0.moveTo(size.width*0.4995083,size.height*0.2401000);
path0.quadraticBezierTo(size.width*0.5840167,size.height*0.2406000,size.width*0.6666667,size.height*0.1420143);
path0.lineTo(size.width*0.9996583,size.height*0.1441000);
path0.lineTo(size.width,size.height);
path0.lineTo(0,size.height);
path0.lineTo(0,size.height*0.1422571);
path0.lineTo(size.width*0.3358333,size.height*0.1442857);
path0.quadraticBezierTo(size.width*0.4136083,size.height*0.2398857,size.width*0.4995083,size.height*0.2401000);
path0.close();
canvas.drawPath(path0, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}

How can I draw a diagonal line inside a container?

The container has an image as a child. I need a line on top of that (diagonally from top right to bottom left).
Use a CustomPainter
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 80),
child: Container(
width: 300,
height: 400,
color: Colors.yellow,
child: CustomPaint(painter: LinePainter()),
),
),
),
);
}
}
class LinePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final p1 = Offset(size.width, 0);
final p2 = Offset(0, size.height);
final paint = Paint()
..color = Colors.black
..strokeWidth = 4;
canvas.drawLine(p1, p2, paint);
}
#override
bool shouldRepaint(LinePainter oldDelegate) => false;
}
You need to use clippath To do that
like this
class CustomClipPath extends CustomClipper<Path> {
var radius=10.0;
#override
Path getClip(Size size) {
Path path = Path();
path.lineTo(0, 200);
path.lineTo(200,200);
path.lineTo(260,0);
path.lineTo(30, 0);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

Animated Curve Line - Flutter

Is it possible to somehow do in flutter what is shown in the GIF?
And so that the starting point always displays a number (in what position this point is at the moment), in the range from 0-100.
EDIT: The animation is now similar to the one in GIF
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 3)
);
late final Size size = const Size(400,400);
late Path path = Path()
..moveTo(3, size.height-4.5)
..quadraticBezierTo(
size.width, size.height,
size.width-4.5, 3,
);
late PathAnimation pathAnimation = PathAnimation(path: path);
#override
void initState() {
super.initState();
_controller.forward();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: const Text('Material App Bar'),
),
body: Center(
child: ClipRect(
child: AnimatedBuilder(
animation: _controller,
child: Container(
alignment: Alignment.center,
height: size.height,
width: size.width,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.black,
width: 3,
)
),
),
builder: (context, child) {
return CustomPaint(
foregroundPainter: PathPainter(
animation: _controller.value,
pathAnimation: pathAnimation,
),
child: child
);
}
),
),
),
),
);
}
}
class PathAnimation {
final Path path;
Path currentPath = Path();
late final List<PathMetric> pathSegments;
late final double totalLength;
double currentLength = 0;
int currentPathIndex = 0;
PathAnimation({
required this.path
}) {
pathSegments = path.computeMetrics().toList();
totalLength = pathSegments.fold(0, (value, element) => value + element.length);
}
Path getCurrentPath(double animation) {
while (animation > (currentLength + pathSegments[currentPathIndex].length) / totalLength) {
double segmentLength = pathSegments[currentPathIndex].length;
currentPath.addPath(
pathSegments[currentPathIndex].extractPath(0, segmentLength),
Offset.zero
);
currentPathIndex++;
currentLength += segmentLength;
}
if (currentPathIndex >= pathSegments.length) return currentPath;
double missingPartLength = animation - currentLength / totalLength;
double newSegmentLength = pathSegments[currentPathIndex].length;
return
currentPath..addPath(
pathSegments[currentPathIndex].extractPath(0, missingPartLength * newSegmentLength),
Offset.zero
);
}
}
class PathPainter extends CustomPainter{
double animation;
PathAnimation pathAnimation;
PathPainter({
required this.animation,
required this.pathAnimation,
});
#override
void paint(Canvas canvas, Size size) {
canvas.drawPath(
pathAnimation.getCurrentPath(animation),
Paint()
..style = PaintingStyle.stroke
..strokeWidth = 3
..color = Colors.red
);
}
#override
bool shouldRepaint(PathPainter oldDelegate) {
return animation != oldDelegate.animation;
}
}

Pass a class as method parameter in Dart

Suppose this class:
class SimpleRectPaint extends Object {
static CustomPaint build( ParamsBundle paramBundle ) {
return CustomPaint(
painter: SimpleRectPainter( paramBundle: paramBundle ),
child: Container(width: paramBundle.width, height: paramBundle.height)
);
}
}
I'd like to abstract the class SimpleRectPaint by means of a ClassReference parameter someClass and make the method more generic. Unfortunately, this isn't valid code:
class SimpleRectPaint extends Object {
static CustomPaint build( ParamsBundle paramBundle, ClassReference someClass ) {
return CustomPaint(
painter: someClass( paramBundle: paramBundle ),
child: Container(width: paramBundle.width, height: paramBundle.height)
);
}
}
Q: How do I have to write it instead?
You could do that by passing a CustomPainterCreator:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: 'Generic Painter',
home: Scaffold(
body: MyWidget(),
),
),
);
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: 200,
height: 200,
child: Stack(
fit: StackFit.expand,
children: [
Background(),
MyPainter(creator: RectPainter.creator, color: Color(0xFF104C91)),
MyPainter(creator: OvalPainter.creator, color: Color(0xFF1F8AC0)),
],
),
),
);
}
}
class Background extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Color(0xFFEFC9AF),
border: Border.all(width: 3.0),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
);
}
}
typedef CustomPainterCreator(Color color);
class MyPainter extends StatelessWidget {
final CustomPainterCreator creator;
final Color color;
const MyPainter({
Key key,
this.creator,
this.color,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomPaint(
painter: creator(color),
);
}
}
class OvalPainter extends CustomPainter {
static CustomPainterCreator creator = (color) => OvalPainter(color: color);
final Color color;
OvalPainter({this.color = Colors.green});
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
canvas.drawOval(
Rect.fromLTWH(size.width * .4, size.height * .15, size.width * .5,
size.height * .5),
paint,
);
}
#override
bool shouldRepaint(OvalPainter oldDelegate) => false;
}
class RectPainter extends CustomPainter {
static CustomPainterCreator creator = (color) => RectPainter(color: color);
final Color color;
RectPainter({this.color = Colors.indigo});
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(size.width * .15, size.height * .25, size.width * .6,
size.height * .6),
Radius.circular(20)),
paint,
);
}
#override
bool shouldRepaint(RectPainter oldDelegate) => false;
}
But, though the exercise is interesting... Why?
Instead of:
MyPainter(creator: RectPainter.creator, color: Color(0xFF104C91)),
You can just do:
CustomPaint(painter: RectPainter(color: Color(0xFF104C91))),
If, not, what is the specific needs that would require more abstraction?

How to make this arc in flutter

I want to work exactly like this image with the circles inside it, how can I do it?
Here is your widget
Center(
child: Container(
width: 200,
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20.0)),
gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFF9B6EEF), Color(0xFF715ED7)]),
),
child: ClipRect(child: CustomPaint(painter: CirclePainter())),
),
),
CustomPainter class for rings inside
class CirclePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = Colors.white10
..style = PaintingStyle.stroke
..strokeWidth = 25;
canvas.drawCircle(Offset.zero, 60, paint);
canvas.drawCircle(Offset(size.width, size.height), 60, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
Result
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SO(),
debugShowCheckedModeBanner: false,
);
}
}
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ClipRRect(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24)),
child: CustomPaint(
size: Size(250, 200),
painter: SOP(
fillColor: Colors.indigo,
spreadColor: Colors.indigoAccent,
spread: 25,
radius: 100,
),
),
),
),
);
}
}
class SOP extends CustomPainter {
final double spread; //the thickness of inner circles
final Color spreadColor; //the color of inner circles
final Color fillColor; //the background color
final double radius; //the radius of inner circles
final Paint p;
SOP({
#required this.spread,
#required this.spreadColor,
#required this.fillColor,
#required this.radius,
}) : p = Paint()
..strokeWidth = spread
..style = PaintingStyle.stroke
..color = spreadColor;
#override
void paint(Canvas canvas, Size size) {
canvas.drawColor(fillColor, BlendMode.src);
canvas.drawCircle(Offset(0, 0), radius, p);
canvas.drawCircle(Offset(size.width, size.height), radius, p);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}