Skip to content

Instantly share code, notes, and snippets.

@imaNNeo
Last active October 9, 2020 22:14
Show Gist options
  • Save imaNNeo/6caaf95c7c11a8f096630135c2f52776 to your computer and use it in GitHub Desktop.
Save imaNNeo/6caaf95c7c11a8f096630135c2f52776 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(home: MyHomePage()));
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool controlPoint2Selected = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'control point 1',
style: TextStyle(
color: controlPoint2Selected ? Colors.green.withOpacity(0.5) : Colors.green,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Switch(
value: controlPoint2Selected,
onChanged: (value) {
setState(() {
controlPoint2Selected = value;
});
},
activeColor: Colors.red,
activeTrackColor: Colors.red.withOpacity(0.4),
inactiveThumbColor: Colors.green,
inactiveTrackColor: Colors.green.withOpacity(0.4),
),
Text(
'control point 2',
style: TextStyle(
color: controlPoint2Selected ? Colors.red : Colors.red.withOpacity(0.5),
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
],
),
SizedBox(
height: 48,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 48.0),
child: MyCurvedLine(
controlPoint2Selected: controlPoint2Selected,
),
),
],
),
),
);
}
}
class MyCurvedLine extends StatefulWidget {
final double height;
final bool controlPoint2Selected;
const MyCurvedLine({
Key key,
this.controlPoint2Selected,
this.height = 74,
}) : super(key: key);
@override
_BottomSheetState createState() => _BottomSheetState();
}
class _BottomSheetState extends State<MyCurvedLine> {
Offset controlPoint1 = Offset.zero, controlPoint2 = Offset.zero;
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (details) {
setState(() {
if (widget.controlPoint2Selected) {
controlPoint2 = details.localPosition;
} else {
controlPoint1 = details.localPosition;
}
});
},
child: CustomPaint(
painter: _MyBottomSheetCustomPainter(controlPoint1, controlPoint2),
size: Size(
double.infinity,
widget.height,
),
),
);
}
}
class _MyBottomSheetCustomPainter extends CustomPainter {
final Offset controlPoint1, controlPoint2;
final Paint linePaint = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 2;
_MyBottomSheetCustomPainter(this.controlPoint1, this.controlPoint2);
@override
void paint(Canvas canvas, Size size) {
Path p = new Path();
final startPoint = Offset(0, size.height / 2);
p.moveTo(startPoint.dx, startPoint.dy);
final targetPoint = Offset(size.width, size.height / 2);
p.cubicTo(
controlPoint1.dx,
controlPoint1.dy,
controlPoint2.dx,
controlPoint2.dy,
targetPoint.dx,
targetPoint.dy,
);
canvas.drawPath(p, linePaint);
drawPoint(canvas, startPoint, offset: Offset(-14, 8));
drawPoint(canvas, targetPoint, offset: Offset(-24, -20));
drawPoint(
canvas,
controlPoint1,
color: Colors.green,
offset: Offset(-20, -24),
pointSize: 6,
);
drawPoint(
canvas,
controlPoint2,
color: Colors.red,
offset: Offset(-40, 8),
pointSize: 6,
);
}
void drawPoint(
Canvas canvas,
Offset point, {
String title = '',
Color color = Colors.black,
Offset offset = Offset.zero,
double pointSize = 4,
}) {
canvas.drawCircle(point, pointSize, Paint()..color = color);
final textPainter = TextPainter(
text: TextSpan(
text: '$title(${point.dx.toInt()}, ${point.dy.toInt()})',
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 12)),
textDirection: TextDirection.ltr,
textAlign: TextAlign.left,
);
textPainter.layout();
textPainter.paint(canvas, point + offset);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment