flutter怎么画层级虚线?

flutter怎么画层级虚线?

阅读 675
avatarAI BotBETA

在 Flutter 中绘制层级虚线,你可以使用 CustomPaint 小部件结合 Canvas 类来绘制自定义图形。以下是一个示例代码,展示了如何在 Flutter 中绘制层级虚线:

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {

return MaterialApp(
  home: Scaffold(
    appBar: AppBar(
      title: Text('层级虚线示例'),
    ),
    body: Center(
      child: CustomPaint(
        size: Size(double.infinity, double.infinity),
        painter: DashedLinePainter(),
      ),
    ),
  ),
);

}
}

class DashedLinePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {

final Paint paint = Paint()
  ..color = Colors.black
  ..strokeWidth = 2.0
  ..style = PaintingStyle.stroke;

// 画第一条水平线
double dashLength = 10.0;
double gapLength = 10.0;
double offsetX = 0.0;
double offsetY = 50.0; // y坐标,可以根据需要调整

double xPosition = 0.0;
while (xPosition < size.width) {
  canvas.drawLine(
    Offset(xPosition, offsetY),
    Offset(xPosition + dashLength, offsetY),
    paint,
  );
  xPosition += dashLength + gapLength;
}

// 画第二条水平线,稍微下移以形成层级效果
offsetY += 20.0; // 下移距离,可以根据需要调整
xPosition = 0.0;
while (xPosition < size.width) {
  canvas.drawLine(
    Offset(xPosition, offsetY),
    Offset(xPosition + dashLength, offsetY),
    paint,
  );
  xPosition += dashLength + gapLength;
}

}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {

return false;

}
}

这个示例代码展示了如何使用 CustomPaintCanvas 来绘制两条水平虚线,它们之间有一定的垂直距离以形成层级效果。你可以根据需要调整虚线的颜色、粗细、间距以及层级之间的距离。

1 个回答

可以使用CustomPaint和Paint来绘制虚线,通过递归或循环的方式处理多层级结构,每个层级使用不同的缩进和虚线样式来表示层次关系。最终可以实现类似于你图片中展示的那种带有层级缩进的虚线树状结构效果。
参考代码:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '层级虚线示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('层级虚线示例'),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const HierarchyItem(
                title: '民事',
                level: 0,
                isLast: false,
              ),
              const HierarchyItem(
                title: '刑事',
                level: 0,
                isLast: false,
              ),
              const HierarchyItem(
                title: '行政',
                level: 0,
                isLast: false,
              ),
              const HierarchyItem(
                title: '国家赔偿',
                level: 0,
                isLast: false,
              ),
              const HierarchyItem(
                title: '司法赔偿',
                level: 1,
                isLast: false,
              ),
              const HierarchyItem(
                title: '违法司法罚款赔偿',
                level: 2,
                isLast: false,
              ),
              const HierarchyItem(
                title: '违法司法拘留赔偿',
                level: 2,
                isLast: false,
              ),
              const HierarchyItem(
                title: '违法保全赔偿',
                level: 2,
                isLast: false,
              ),
              const HierarchyItem(
                title: '错误执行赔偿',
                level: 2,
                isLast: false,
              ),
              const HierarchyItem(
                title: '刑事赔偿',
                level: 1,
                isLast: false,
              ),
              const HierarchyItem(
                title: '行政赔偿',
                level: 1,
                isLast: false,
              ),
              const HierarchyItem(
                title: '合作业务',
                level: 0,
                isLast: true,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class HierarchyItem extends StatelessWidget {
  final String title;
  final int level;
  final bool isLast;

  const HierarchyItem({
    super.key,
    required this.title,
    required this.level,
    required this.isLast,
  });

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: HierarchyLinePainter(
        level: level,
        isLast: isLast,
      ),
      child: Container(
        padding: EdgeInsets.only(left: 40.0 * level),
        height: 40,
        child: Row(
          children: [
            if (level > 0)
              const SizedBox(width: 20), // 为子级添加额外的缩进
            Text(
              title,
              style: const TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
    );
  }
}

class HierarchyLinePainter extends CustomPainter {
  final int level;
  final bool isLast;

  HierarchyLinePainter({
    required this.level,
    required this.isLast,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.grey
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;

    // 设置虚线效果
    paint.strokeCap = StrokeCap.round;
    final dashWidth = 5.0;
    final dashSpace = 3.0;
    final dashes = <double>[dashWidth, dashSpace];
    final path = Path();

    // 绘制垂直连接线
    if (level > 0) {
      double startX = 40.0 * (level - 1) + 20;
      path.moveTo(startX, 0);
      path.lineTo(startX, size.height);

      // 绘制水平连接线
      path.moveTo(startX, size.height / 2);
      path.lineTo(startX + 20, size.height / 2);
    }

    // 使用虚线效果绘制路径
    canvas.drawPath(
      dashPath(
        path,
        dashArray: CircularIntervalList<double>(dashes),
      ),
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

// 辅助类:创建虚线路径
Path dashPath(Path path, {required CircularIntervalList<double> dashArray}) {
  final dashPath = Path();
  final distance = path.computeMetrics().first;
  var started = true;
  var remaining = distance.length;
  var start = 0.0;

  while (remaining > 0) {
    final len = dashArray.next;
    if (len > remaining) {
      if (started) dashPath.addPath(
        path,
        Offset.zero,
        from: start,
        to: distance.length,
      );
      break;
    }

    if (started) {
      dashPath.addPath(
        path,
        Offset.zero,
        from: start,
        to: start + len,
      );
    }

    start += len;
    remaining -= len;
    started = !started;
  }

  return dashPath;
}

// 辅助类:循环列表
class CircularIntervalList<T> {
  final List<T> _values;
  int _index = 0;

  CircularIntervalList(this._values);

  T get next {
    if (_index >= _values.length) _index = 0;
    return _values[_index++];
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题