ibr*_*him 3 custom-painting flutter
我的页面中有这个自定义路径
class TestPathPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2.0
..color = Colors.black;
var x = size.width;
var y = size.height;
print(x);
var path = Path()
..moveTo(x, y / 4)
..lineTo(x * 0.95, y / 4)
..lineTo(x * 0.95, y / 3)
..lineTo(x * 0.99, y / 3)
..lineTo(x * 0.99, y / 3.7)
..lineTo(x * 0.955, y / 3.7)
..lineTo(x * 0.955, y / 3.15)
..lineTo(x * 0.98, y / 3.15)
..lineTo(x * 0.98, y / 3.5)
..lineTo(x * 0.94, y / 3.5) // <==== I want to display a Checkbox here
..lineTo(x * 0.94, y / 2)
..lineTo(x * 0.91, y / 2)
..lineTo(x * 0.91, y / 1.65)
..lineTo(x * 0.94, y / 1.65)
..lineTo(x * 0.94, y / 1.4)
..lineTo(x * 0.91, y / 1.4);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(TestPathPainter oldDelegate) => false;
}
Run Code Online (Sandbox Code Playgroud)
我如何在此路径上的某处绘制/渲染小部件(例如复选框)?
我尝试使用堆叠小部件并定位复选框,但这在每个设备上看起来都不同。
将小部件放置在屏幕上特定位置的最简单方法是使用堆栈和Positioned小部件。
不过,我们面临的问题是定位(top, right, bottom, left)指的是小部件的侧面child而不是中心。
所以,我们需要调整定位。
SizedBox > CenterPositioned(
left: point.dx * width - 24,
top: point.dy * height - 24,
child: SizedBox(
width: 48,
height: 48,
child: Center(
child: Checkbox(
value: true,
onChanged: (_) {},
),
),
),
),
Run Code Online (Sandbox Code Playgroud)
48选择它是为了确保我们大于完整尺寸(包括由materialTapTargetSize和 引起的填充)visualDensity。
这引出了第二个解决方案。
Checkbox尽管复选框具有“ static const widthof” 18,但它可能会根据“ ”materialTapTargetSize和“ ”而有所不同visualDensity。
如果我们看一下GitHub 上的源代码CheckBox:
我们可以定义一个ComputeCheckBoxSize:
double computeCheckBoxSize(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final MaterialTapTargetSize effectiveMaterialTapTargetSize =
themeData.checkboxTheme.materialTapTargetSize ??
themeData.materialTapTargetSize;
final VisualDensity effectiveVisualDensity =
themeData.checkboxTheme.visualDensity ?? themeData.visualDensity;
Size size;
switch (effectiveMaterialTapTargetSize) {
case MaterialTapTargetSize.padded:
size = const Size(kMinInteractiveDimension, kMinInteractiveDimension);
break;
case MaterialTapTargetSize.shrinkWrap:
size = const Size(
kMinInteractiveDimension - 8.0, kMinInteractiveDimension - 8.0);
break;
}
size += effectiveVisualDensity.baseSizeAdjustment;
return size.longestSide;
}
Run Code Online (Sandbox Code Playgroud)
我们的Positioned小部件可以进一步简化为:
Positioned(
left: point.dx * width - checkBoxSize / 2,
top: point.dy * height - checkBoxSize / 2,
child: Checkbox(
value: true,
onChanged: (_) {},
),
)
Run Code Online (Sandbox Code Playgroud)
import 'dart:math' show Random;
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
double checkBoxSize = computeCheckBoxSize(context);
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
final height = constraints.biggest.height;
final width = constraints.biggest.width;
return Stack(
children: [
Container(color: Colors.amber.shade100),
Positioned.fill(child: CustomPaint(painter: TestPathPainter())),
...points
.map(
(point) => Positioned(
left: point.dx * width - checkBoxSize / 2,
top: point.dy * height - checkBoxSize / 2,
child: Checkbox(
value: true,
onChanged: (_) {},
),
),
)
.toList(),
],
);
},
),
);
}
}
double computeCheckBoxSize(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final MaterialTapTargetSize effectiveMaterialTapTargetSize =
themeData.checkboxTheme.materialTapTargetSize ??
themeData.materialTapTargetSize;
final VisualDensity effectiveVisualDensity =
themeData.checkboxTheme.visualDensity ?? themeData.visualDensity;
Size size;
switch (effectiveMaterialTapTargetSize) {
case MaterialTapTargetSize.padded:
size = const Size(kMinInteractiveDimension, kMinInteractiveDimension);
break;
case MaterialTapTargetSize.shrinkWrap:
size = const Size(
kMinInteractiveDimension - 8.0, kMinInteractiveDimension - 8.0);
break;
}
size += effectiveVisualDensity.baseSizeAdjustment;
print(size);
return size.longestSide;
}
class TestPathPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2.0
..color = Colors.black;
final path = Path()
..moveTo(
points[0].dx * size.width,
points[0].dy * size.height,
);
points.sublist(1).forEach(
(point) => path.lineTo(
point.dx * size.width,
point.dy * size.height,
),
);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(TestPathPainter oldDelegate) => false;
}
final random = Random();
final List<Offset> points = List.generate(
10,
(index) => Offset(.1 + random.nextDouble() * .8, .1 + index * .8 / 9),
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3977 次 |
| 最近记录: |