Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 在特定路径位置将绘制小部件颤振到画布_Flutter_Custom Painting - Fatal编程技术网

Flutter 在特定路径位置将绘制小部件颤振到画布

Flutter 在特定路径位置将绘制小部件颤振到画布,flutter,custom-painting,Flutter,Custom Painting,我的页面中有此自定义路径 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.w

我的页面中有此自定义路径

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;
}
类TestPathPainter扩展了CustomPainter{
@凌驾
空心油漆(帆布,尺寸){
最终油漆=油漆()
…风格=绘画风格笔划
..冲程宽度=2.0
…颜色=颜色。黑色;
var x=大小。宽度;
var y=尺寸。高度;
印刷品(x);
var path=path()
…移动到(x,y/4)
…直线至(x*0.95,y/4)
…直线至(x*0.95,y/3)
..直线至(x*0.99,y/3)
..直线至(x*0.99,y/3.7)
..直线至(x*0.955,y/3.7)
..线路至(x*0.955,y/3.15)
…直线至(x*0.98,y/3.15)
…直线至(x*0.98,y/3.5)
…lineTo(x*0.94,y/3.5)//假;
}
如何在此路径上的某处绘制/呈现小部件(例如复选框)

我尝试使用一个堆叠的小部件并定位复选框,但这在每个设备上看起来都不一样。

将小部件定位到屏幕上特定位置的最简单方法是使用堆栈和定位的小部件

尽管如此,我们面临的问题是定位(
顶部
右侧
底部
左侧
)指的是
子部件的侧面,而不是中心

因此,我们需要调整定位

解决方案1-使用
SizedBox>Center
选择了
48
以确保我们的尺寸大于全尺寸(包括
materialTargetSize
visualDensity
造成的填充)

这就引出了第二个解决方案

解决方案2:计算
复选框的完整大小
尽管该复选框的
静态常量宽度
18
,但它可能会因
材质目标大小和
视觉密度而有所不同

如果我们看一下:

我们可以定义一个
ComputeTechKboxSize

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;
}
我们的
定位
小部件可以进一步简化为:

Positioned(
  left: point.dx * width - checkBoxSize / 2,
  top: point.dy * height - checkBoxSize / 2,
  child: Checkbox(
    value: true,
    onChanged: (_) {},
  ),
)
完整源代码
import'dart:math'随机显示;
进口“包装:颤振/材料.省道”;
void main(){
runApp(
材料聚丙烯(
debugShowCheckedModeBanner:false,
标题:“颤振演示”,
主页:主页(),
),
);
}
类主页扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
double checkBoxSize=computeCheckBoxSize(上下文);
返回脚手架(
正文:布局生成器(
生成器:(上下文、约束){
最终高度=约束。最大。高度;
最终宽度=constraints.max.width;
返回堆栈(
儿童:[
容器(颜色:Colors.amber.shade100),
Positioned.fill(子项:CustomPaint(painter:TestPathPainter()),
…点
.地图(
(点)=>定位(
左:point.dx*宽度-复选框大小/2,
顶部:point.dy*高度-复选框大小/2,
子项:复选框(
价值观:正确,
一旦改变:({},
),
),
)
.toList(),
],
);
},
),
);
}
}
double ComputeCheckBox大小(BuildContext上下文){
最终主题数据主题数据=Theme.of(上下文);
最终材料目标尺寸有效材料目标尺寸=
themeData.checkboxTheme.MaterialTaptTargetSize??
MEMEDATA.materialTapTargetSize;
最终视觉密度有效视觉密度=
主题数据.checkboxTheme.visualDensity??主题数据.visualDensity;
大小;
开关(有效材料目标尺寸){
案例材料ptargetsize.padded:
大小=常量大小(kMinInteractiveDimension,kMinInteractiveDimension);
打破
案例材料目标尺寸.shrinkWrap:
大小=常量大小(
KminiInteractiveDimension-8.0,KminiInteractiveDimension-8.0);
打破
}
大小+=有效视觉密度。基本大小调整;
印刷品(尺寸);
返回大小。最长边;
}
类TestPathPainter扩展了CustomPainter{
@凌驾
空心油漆(帆布,尺寸){
最终油漆=油漆()
…风格=绘画风格笔划
..冲程宽度=2.0
…颜色=颜色。黑色;
最终路径=路径()
…移动到(
点[0]。dx*size.width,
点[0].dy*size.height,
);
点。子列表(1)。forEach(
(点)=>path.lineTo(
point.dx*size.width,
point.dy*size.height,
),
);
画布.绘制路径(路径,绘制);
}
@凌驾
bool应该重新绘制(TestPathPainter oldDelegate)=>false;
}
最终随机=随机();
最终列表点=List.generate(
10,
(索引)=>偏移量(.1+随机.nextDouble()*.8.1+索引*.8/9),
);
Positioned(
  left: point.dx * width - checkBoxSize / 2,
  top: point.dy * height - checkBoxSize / 2,
  child: Checkbox(
    value: true,
    onChanged: (_) {},
  ),
)
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),
);