How to add line dash in Flutter
Asked Answered
D

22

60

How to make a line dash in Flutter like this?

Image

Disassemble answered 3/1, 2019 at 9:48 Comment(4)
Did you try something? Can you add that thing too?Ensoul
github.com/flutter/flutter/issues/4858Teodoro
try Text('------------------------------------')Arvid
if you want to draw it as a dashed path on the canvas use this package: pub.dartlang.org/packages/path_drawingItin
E
105

As a workaround, in your case, you can do something like this

class MySeparator extends StatelessWidget {
  const MySeparator({Key? key, this.height = 1, this.color = Colors.black})
      : super(key: key);
  final double height;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        final boxWidth = constraints.constrainWidth();
        const dashWidth = 10.0;
        final dashHeight = height;
        final dashCount = (boxWidth / (2 * dashWidth)).floor();
        return Flex(
          children: List.generate(dashCount, (_) {
            return SizedBox(
              width: dashWidth,
              height: dashHeight,
              child: DecoratedBox(
                decoration: BoxDecoration(color: color),
              ),
            );
          }),
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          direction: Axis.horizontal,
        );
      },
    );
  }
}

and use it const MySeparator()


class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Material(
        child: Container(
          color: Colors.blue,
          child: Center(
            child: Container(
              height: 600,
              width: 350,
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.all(Radius.circular(16.0)),
              ),
              child: Flex(
                direction: Axis.vertical,
                children: [
                  Expanded(child: Container()),
                  const MySeparator(color: Colors.grey),
                  Container(height: 200),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

demo

Exum answered 3/1, 2019 at 14:58 Comment(0)
B
58
class DashedLinePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    double dashWidth = 9, dashSpace = 5, startX = 0;
    final paint = Paint()
      ..color = Colors.grey
      ..strokeWidth = 1;
    while (startX < size.width) {
      canvas.drawLine(Offset(startX, 0), Offset(startX + dashWidth, 0), paint);
      startX += dashWidth + dashSpace;
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}
Blavatsky answered 13/11, 2019 at 14:10 Comment(3)
Use it like CustomPaint(painter: DashedLinePainter());Jubilee
This answer deserves more votes and should be accepted answer.Downtoearth
This answer is the right solution.Remus
S
35
// garis putus putus
Row(
children: List.generate(150~/10, (index) => Expanded(
 child: Container(
  color: index%2==0?Colors.transparent
  :Colors.grey,
  height: 2,
 ),
 )),
),
Strobe answered 11/3, 2020 at 5:4 Comment(5)
While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.Sato
this is the simplest answer to implement without any dependency.Punishable
Looks good trick but why 150~/10 ? why not you used just a number like 15, 16, 17.... ?Beverage
@Beverage for example, you want to apply the width of the widget or screen, then divide by how many lines you want and the "~" sign to give an integer value, and if you want it to be even simpler, you can use your suggestion with fixed numbers like 5, 6,10 and so onStrobe
If you want it to start with a dot (colored dot) instead of transparent. first index 0 is even color: index.isEven ? Colors.grey : Colors.transparentOperculum
S
20

The following code creates a dashed path not only for lines, but for any path you want dashed.

Demo:

enter image description here

The idea is to take the originalPath and move along it, alternately adding dashes and gaps until the entire path has been extracted:

Path _getDashedPath(
  Path originalPath,
  double dashLength,
  double dashGapLength,
) {
  final metricsIterator = originalPath.computeMetrics().iterator;
  while (metricsIterator.moveNext()) {
    final metric = metricsIterator.current;
    _dashedPathProperties.extractedPathLength = 0.0;
    while (_dashedPathProperties.extractedPathLength < metric.length) {
      if (_dashedPathProperties.addDashNext) {
        _dashedPathProperties.addDash(metric, dashLength);
      } else {
        _dashedPathProperties.addDashGap(metric, dashGapLength);
      }
    }
  }
  return _dashedPathProperties.path;
}

I created a class DashedPathProperties to track things like the currently extractedPathLength or the _remainingDashLength, which becomes relevant if the originalPath consists of several sub-paths and a dash (or dash gap) must be continued on the next sub-path:

class DashedPathProperties {
  double extractedPathLength;
  Path path;

  final double _dashLength;
  double _remainingDashLength;
  double _remainingDashGapLength;
  bool _previousWasDash;

  DashedPathProperties({
    required this.path,
    required double dashLength,
    required double dashGapLength,
  })  : assert(dashLength > 0.0, 'dashLength must be > 0.0'),
        assert(dashGapLength > 0.0, 'dashGapLength must be > 0.0'),
        _dashLength = dashLength,
        _remainingDashLength = dashLength,
        _remainingDashGapLength = dashGapLength,
        _previousWasDash = false,
        extractedPathLength = 0.0;

  //...
}

You can use like this (you could wrap your CustomPaint in a ClipRect if you want to make sure that the painter cannot paint outside of the bounds):

CustomPaint(
  painter: DashedPathPainter(
    originalPath: Path()
      ..addOval(
        const Rect.fromLTWH(0, 0, 100, 100),
      ),
    pathColor: Colors.white,
  ),
  size: const Size(100.0, 100.0),
)

Full example code you can run in DartPad:

import 'dart:ui' as ui;
import 'dart:math' as math;

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: const Scaffold(
        body: Center(
          child: ExampleDashedPath(),
        ),
      ),
    );
  }
}

class ExampleDashedPath extends StatelessWidget {
  const ExampleDashedPath({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const SizedBox(height: 50),
        CustomPaint(
          painter: DashedPathPainter(
            originalPath: Path()..lineTo(100, 0),
            pathColor: Colors.red,
            strokeWidth: 5.0,
            dashGapLength: 10.0,
            dashLength: 10.0,
          ),
          size: const Size(100.0, 2.0),
        ),
        const SizedBox(height: 50),
        CustomPaint(
          painter: DashedPathPainter(
            originalPath: Path()
              ..addOval(
                const Rect.fromLTWH(0, 0, 100, 100),
              ),
            pathColor: Colors.white,
          ),
          size: const Size(100.0, 100.0),
        ),
        const SizedBox(height: 50),
        CustomPaint(
          painter: DashedPathPainter(
            originalPath: Path()
              ..addRect(
                const Rect.fromLTWH(0, 0, 100, 100),
              )
              ..lineTo(100, 100),
            pathColor: Colors.grey,
            strokeWidth: 2.0,
            dashLength: 25.0,
          ),
          size: const Size(100.0, 100.0),
        ),
      ],
    );
  }
}

class DashedPathPainter extends CustomPainter {
  final Path originalPath;
  final Color pathColor;
  final double strokeWidth;
  final double dashGapLength;
  final double dashLength;
  late DashedPathProperties _dashedPathProperties;

  DashedPathPainter({
    required this.originalPath,
    required this.pathColor,
    this.strokeWidth = 3.0,
    this.dashGapLength = 5.0,
    this.dashLength = 10.0,
  });

  @override
  void paint(Canvas canvas, Size size) {
    _dashedPathProperties = DashedPathProperties(
      path: Path(),
      dashLength: dashLength,
      dashGapLength: dashGapLength,
    );
    final dashedPath = _getDashedPath(originalPath, dashLength, dashGapLength);
    canvas.drawPath(
      dashedPath,
      Paint()
        ..style = PaintingStyle.stroke
        ..color = pathColor
        ..strokeWidth = strokeWidth,
    );
  }

  @override
  bool shouldRepaint(DashedPathPainter oldDelegate) =>
      oldDelegate.originalPath != originalPath ||
      oldDelegate.pathColor != pathColor ||
      oldDelegate.strokeWidth != strokeWidth ||
      oldDelegate.dashGapLength != dashGapLength ||
      oldDelegate.dashLength != dashLength;

  Path _getDashedPath(
    Path originalPath,
    double dashLength,
    double dashGapLength,
  ) {
    final metricsIterator = originalPath.computeMetrics().iterator;
    while (metricsIterator.moveNext()) {
      final metric = metricsIterator.current;
      _dashedPathProperties.extractedPathLength = 0.0;
      while (_dashedPathProperties.extractedPathLength < metric.length) {
        if (_dashedPathProperties.addDashNext) {
          _dashedPathProperties.addDash(metric, dashLength);
        } else {
          _dashedPathProperties.addDashGap(metric, dashGapLength);
        }
      }
    }
    return _dashedPathProperties.path;
  }
}

class DashedPathProperties {
  double extractedPathLength;
  Path path;

  final double _dashLength;
  double _remainingDashLength;
  double _remainingDashGapLength;
  bool _previousWasDash;

  DashedPathProperties({
    required this.path,
    required double dashLength,
    required double dashGapLength,
  })  : assert(dashLength > 0.0, 'dashLength must be > 0.0'),
        assert(dashGapLength > 0.0, 'dashGapLength must be > 0.0'),
        _dashLength = dashLength,
        _remainingDashLength = dashLength,
        _remainingDashGapLength = dashGapLength,
        _previousWasDash = false,
        extractedPathLength = 0.0;

  bool get addDashNext {
    if (!_previousWasDash || _remainingDashLength != _dashLength) {
      return true;
    }
    return false;
  }

  void addDash(ui.PathMetric metric, double dashLength) {
    // Calculate lengths (actual + available)
    final end = _calculateLength(metric, _remainingDashLength);
    final availableEnd = _calculateLength(metric, dashLength);
    // Add path
    final pathSegment = metric.extractPath(extractedPathLength, end);
    path.addPath(pathSegment, Offset.zero);
    // Update
    final delta = _remainingDashLength - (end - extractedPathLength);
    _remainingDashLength = _updateRemainingLength(
      delta: delta,
      end: end,
      availableEnd: availableEnd,
      initialLength: dashLength,
    );
    extractedPathLength = end;
    _previousWasDash = true;
  }

  void addDashGap(ui.PathMetric metric, double dashGapLength) {
    // Calculate lengths (actual + available)
    final end = _calculateLength(metric, _remainingDashGapLength);
    final availableEnd = _calculateLength(metric, dashGapLength);
    // Move path's end point
    ui.Tangent tangent = metric.getTangentForOffset(end)!;
    path.moveTo(tangent.position.dx, tangent.position.dy);
    // Update
    final delta = end - extractedPathLength;
    _remainingDashGapLength = _updateRemainingLength(
      delta: delta,
      end: end,
      availableEnd: availableEnd,
      initialLength: dashGapLength,
    );
    extractedPathLength = end;
    _previousWasDash = false;
  }

  double _calculateLength(ui.PathMetric metric, double addedLength) {
    return math.min(extractedPathLength + addedLength, metric.length);
  }

  double _updateRemainingLength({
    required double delta,
    required double end,
    required double availableEnd,
    required double initialLength,
  }) {
    return (delta > 0 && availableEnd == end) ? delta : initialLength;
  }
}
Subordinary answered 13/2, 2022 at 9:16 Comment(4)
Brilliant! Didn't even have to change my existing codeFracture
I cannot stress enough how ridiculously good the code is. It deserves more attention.Frederiksen
@Subordinary is there any way to have border radius?Villus
@Villus You just have to pass an originalPath that has rounded corners, e.g. Path()..addRRect(RRect.fromRectAndRadius(const Rect.fromLTWH(0, 0, 100, 100), const Radius.circular(10)))Subordinary
S
13

CustomPainter can help here as well. In this example is a vertical dash line but could be changed easily.

class LineDashedPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()..strokeWidth = 2;
    var max = 35;
    var dashWidth = 5;
    var dashSpace = 5;
    double startY = 0;
    while (max >= 0) {
      canvas.drawLine(Offset(0, startY), Offset(0, startY + dashWidth), paint);
      final space = (dashSpace + dashWidth);
      startY += space;
      max -= space;
    }
  }

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

and that use CustomPaint Widget:

CustomPaint(painter: LineDashedPainter())
Sestina answered 5/5, 2019 at 15:6 Comment(0)
P
12

I have written flutter_dash library for drawing that dash. Just one line and you should have a dash :D

Dash(length: 200, dashColor: Colors.red)

Give it a try!

Pop answered 12/9, 2019 at 2:3 Comment(3)
I don't recomend, this library is not well optimized and will cause your app to be slower to load screensExcitation
@SoufianeGhzal please give me some advices to optimize it, thank youJenna
@LêVũHuy I don't really know what's the issue. go to github please github.com/huy-lv/flutter_dash/issues/2Excitation
B
6

Thank to marksimr answer, here is the code for both vertical and horizontal dash line.

Horizontal usage:

DashLineView(
  fillRate: 0.7,
),

Vertical usage:

DashLineView(
  fillRate: 0.7,
  direction: Axis.vertical,
),

Full code:

class DashLineView extends StatelessWidget {
  final double dashHeight;
  final double dashWith;
  final Color dashColor;
  final double fillRate; // [0, 1] totalDashSpace/totalSpace
  final Axis direction;

  DashLineView(
      {this.dashHeight = 1,
      this.dashWith = 8,
      this.dashColor = Colors.black,
      this.fillRate = 0.5,
      this.direction = Axis.horizontal});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        final boxSize = direction == Axis.horizontal
            ? constraints.constrainWidth()
            : constraints.constrainHeight();
        final dCount = (boxSize * fillRate / dashWith).floor();
        return Flex(
          children: List.generate(dCount, (_) {
            return SizedBox(
              width: direction == Axis.horizontal ? dashWith : dashHeight,
              height: direction == Axis.horizontal ? dashHeight : dashWith,
              child: DecoratedBox(
                decoration: BoxDecoration(color: dashColor),
              ),
            );
          }),
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          direction: direction,
        );
      },
    );
  }
}
Brent answered 14/10, 2021 at 7:38 Comment(0)
S
5
 Row(
    children: List.generate(20, (index) {
                 return Expanded(
                   child: Padding(
                     padding: const EdgeInsets.only(left: 8.0),
                     child: Container(
                       height: 5,
                       width: 10,
                       color: Color(0XFFf2f2f2),
                     ),
                   ),
                 );
               }),
             )

enter image description here

Sandblast answered 29/10, 2021 at 13:51 Comment(1)
this will be not responsiveTragus
A
4

You can use CustomPainter with a linear gradient dashed shader for your lines.

   // GradientRotation(3.14 / 2) — for vertical lines with dashes
   // GradientRotation(0) — for horizontal lines with dashes
   // .createShader(Rect.fromLTWH(0, 0, 10, 10) — 10 is the size of repeated shaders part
   // This method can be tricky if you need a line oriented by some angle.

Paint()..shader = LinearGradient(
                  colors: [Colors.blue, Colors.transparent],
                  stops: [0.5, 0.5],
                  tileMode: TileMode.repeated,
                  transform: GradientRotation(3.14 / 2))
              .createShader(Rect.fromLTWH(0, 0, 10, 10))
          ..style = PaintingStyle.stroke
          ..strokeWidth = 6
Amarillo answered 11/3, 2021 at 19:26 Comment(0)
T
3

enter image description here

Create this class:

class DotWidget extends StatelessWidget {
  final double totalWidth, dashWidth, emptyWidth, dashHeight;

  final Color dashColor;

  const DotWidget({
    this.totalWidth = 300,
    this.dashWidth = 10,
    this.emptyWidth = 5,
    this.dashHeight = 2,
    this.dashColor = Colors.black,
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: List.generate(
        totalWidth ~/ (dashWidth + emptyWidth),
            (_) => Container(
          width: dashWidth,
          height: dashHeight,
          color: dashColor,
          margin: EdgeInsets.only(left: emptyWidth / 2, right: emptyWidth / 2),
        ),
      ),
    );
  }
}

Usage:

Use it like any other widget

 child: DotWidget(
   dashColor: Colors.black,
   dashHeight: 2,
   dashWidth: 100,
 )
Truancy answered 3/7, 2019 at 18:39 Comment(0)
B
3

Vertical dashed line:
I modifed maksimr's example:

class DashedLine extends StatelessWidget {
  final double height;
  final double heightContainer;
  final Color color;

  const DashedLine({this.height = 3, this.color = Colors.black, this.heightContainer = 70});

  @override
  Widget build(BuildContext context) {
    return Container(
      height: heightContainer,
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          final boxHeight = constraints.constrainHeight();
          final dashWidth = 10.0;
          final dashHeight = height;
          final dashCount = (boxHeight / (2 * dashHeight)).floor();
          return Flex(
            children: List.generate(dashCount, (_) {
              return SizedBox(
                width: dashWidth,
                height: dashHeight,
                child: DecoratedBox(
                  decoration: BoxDecoration(color: color),
                ),
              );
            }),
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            direction: Axis.vertical,
          );
        },
      ),
    );
  }
}
Buckthorn answered 9/7, 2020 at 21:14 Comment(0)
C
2

I created a CustomPainter by integrating the solution here and the math from here. This CustomPainter allows to draw a solid line or a dashed line by specifying the length of the dash and the length of the space between dashes. But the best thing is you can even draw the solid or dashed line in all directions. I mean horizontal, vertical, and even diagonal!

This is the code for the CustomPainter:

import 'dart:math';

import 'package:flutter/material.dart';

class LinePainter extends CustomPainter {
  final Offset firstOffset;
  final Offset secondOffset;
  final Color color;
  final double strokeWidth;
  final double dashLength;
  final double dashSpace;

  const LinePainter({
    required this.firstOffset,
    required this.secondOffset,
    this.color = Colors.black,
    this.strokeWidth = 2.0,
    this.dashLength = 4.0,
    this.dashSpace = 4.0,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = strokeWidth;
    _drawDashedLine(
        dashLength, dashSpace, firstOffset, secondOffset, canvas, size, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }

  void _drawDashedLine(double dashLength, double dashSpace, Offset firstOffset,
      Offset secondOffset, Canvas canvas, Size size, Paint paint) {
    var startOffset = firstOffset;

    var intervals = _getDirectionVector(firstOffset, secondOffset).length /
        (dashLength + dashSpace);

    for (var i = 0; i < intervals; i++) {
      var endOffset = _getNextOffset(startOffset, secondOffset, dashLength);

      /// Draw a small line.
      canvas.drawLine(startOffset, endOffset, paint);

      /// Update the starting offset.
      startOffset = _getNextOffset(endOffset, secondOffset, dashSpace);
    }
  }

  Offset _getNextOffset(
    Offset firstOffset,
    Offset secondOffset,
    double smallVectorLength,
  ) {
    var directionVector = _getDirectionVector(firstOffset, secondOffset);

    var rescaleFactor = smallVectorLength / directionVector.length;
    if (rescaleFactor.isNaN || rescaleFactor.isInfinite) {
      rescaleFactor = 1;
    }

    var rescaledVector = Offset(directionVector.vector.dx * rescaleFactor,
        directionVector.vector.dy * rescaleFactor);

    var newOffset = Offset(
        firstOffset.dx + rescaledVector.dx, firstOffset.dy + rescaledVector.dy);

    return newOffset;
  }

  DirectionVector _getDirectionVector(Offset firstVector, Offset secondVector) {
    var directionVector = Offset(
        secondVector.dx - firstVector.dx, secondVector.dy - firstVector.dy);

    var directionVectorLength =
        sqrt(pow(directionVector.dx, 2) + pow(directionVector.dy, 2));

    return DirectionVector(
      vector: directionVector,
      length: directionVectorLength,
    );
  }
}

class DirectionVector {
  final Offset vector;
  final double length;

  const DirectionVector({
    required this.vector,
    required this.length,
  });
}

You can use this CustomPainter by setting up the painter parameter of a CustomPaint widget, like this:

CustomPaint(
  painter: LinePainter(
    firstOffset: Offset(0, 0),
    secondOffset: Offset(10, 10),
  ),
),

The result is shown in the following image:

Dashed line using the CustomPainter

Connolly answered 22/5, 2021 at 19:4 Comment(0)
L
2

When going for the CustomPainter approach, painting a dashed line in any direction can be achieved by a snippet like this:

  void _drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint) {
    const dashLength = 10.0;
    const stride = 2 * dashLength;

    var distance = (end - start).distance;
    while (distance > 0) {
      final remaining = end - start;
      final direction = remaining / remaining.distance;
      final next = start + (direction * dashLength);
      canvas.drawLine(start, next, paint);
      start = start + (direction * stride);
      distance -= stride;
    }
  }

This method should be embedded in your CustomPainter implementation of a CustomPaint widget, like mentioned in the other answers.

Local answered 10/8, 2022 at 10:36 Comment(0)
D
1

Here is the code for horizontal dashed line, like your image. CustomPaint is highly recommended by flutter team for stuff like this. It is fast and efficient for rendering also. You can play with Offset to change the direction.

 class MyClass extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: CustomPaint(
        painter: MyLinePainter(),
      ),
    );
  }
}

class MyLinePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var max = 100;
    var dashWidth, dashSpace = 5;
    double startX = 0;
    final paint = Paint()..color = Colors.grey;
    while (max >= 0) {
      canvas.drawLine(Offset(startX, 0), Offset(startX + dashWidth, 0), paint..strokeWidth = 1);
      final space = (dashSpace + dashWidth);
      startX += space;
      max -= space;
    }
  }
Deprecate answered 5/8, 2019 at 8:21 Comment(0)
C
1

You can use this:

Widget dashedHorizontalLine(){
  return Row(
    children: [
      for (int i = 0; i < 20; i++)
        Expanded(
          child: Row(
            children: [
              Expanded(
                child: Divider(
                  color: AppColors.darkGreen,
                  thickness: 2,
                ),
              ),
              Expanded(
                child: Container(),
              ),
            ],
          ),
        ),
    ],
  );
}
Condiment answered 16/3, 2021 at 19:14 Comment(0)
K
1

I came up with this solution.

Row(                        // Dashed line
    children: [
      for (int i = 0; i < 25; i++)
        Container(
          width: 5,
          height: 1,
          decoration: BoxDecoration(
            border: Border(
              bottom: BorderSide(
                width: 1,
                color: i % 2 == 0
                    ? const Color.fromRGBO(214, 211, 211, 1)
                    : Colors.transparent,
              ),
            ),
          ),
        ),
    ],
  ),

Output:

Output:

Kratz answered 27/9, 2021 at 6:24 Comment(0)
L
0

Try this,

class DotDivider extends StatelessWidget {
  final double width;
  final double height;
  final double gap;
  final Color color;
  final double lineHeight;

  const DotDivider(
      {this.height = 1.0,
      this.color = Colors.black,
      this.width = 2.0,
      this.gap = 2.0,
      this.lineHeight = 10.0});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        final boxWidth = constraints.constrainWidth();
        final dashWidth = width;
        final dashHeight = height;
        final dashCount = (boxWidth / dashWidth).floor();
        return Container(
          height: (lineHeight * 2) + height,
          child: ListView.builder(
            physics: NeverScrollableScrollPhysics(),
            scrollDirection: Axis.horizontal,
            itemCount: dashCount,
            itemBuilder: (BuildContext context, int index) => Center(
              child: Container(
                width: dashWidth,
                height: dashHeight,
                margin:
                    EdgeInsets.symmetric(vertical: lineHeight, horizontal: gap),
                decoration: BoxDecoration(color: color),
              ),
            ),
          ),
        );
      },
    );
  }
}
Lavatory answered 11/10, 2019 at 7:26 Comment(0)
F
0

You should prefer using CustomPainter because it's more performance and suitable for such issues.

class DashLine extends StatelessWidget {
  const DashLine({
    Key key,
    this.color,
    this.dashWidth,
    this.dashSpace,
    this.strokeWidth,
  }) : super(key: key);

  final Color color;
  final double dashWidth;
  final double dashSpace;
  final double strokeWidth;

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _DashLinePainter(
        color: color,
        dashWidth: dashWidth,
        dashSpace: dashSpace,
        strokeWidth: strokeWidth,
      ),
    );
  }
}

class _DashLinePainter extends CustomPainter {
  _DashLinePainter({
    Color color,
    double dashWidth,
    double dashSpace,
    double strokeWidth,
  })  : _color = color ?? Colors.red,
        _dashWidth = dashWidth ?? 5.0,
        _dashSpace = dashSpace ?? 5.0,
        _strokeWidth = strokeWidth ?? 1.0;

  final Color _color;
  final double _dashWidth;
  final double _dashSpace;
  final double _strokeWidth;

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = _color
      ..strokeWidth = _strokeWidth;

    var max = size.width;
    var startX = 0.0;
    while (max >= 0) {
      canvas.drawLine(Offset(startX, 0), Offset(startX + _dashWidth, 0), paint);
      final space = (_dashSpace + _dashWidth);
      startX += space;
      max -= space;
    }
  }

  @override
  bool shouldRepaint(_DashLinePainter oldDelegate) {
    return _color != oldDelegate._color ||
        _dashWidth != oldDelegate._dashWidth ||
        _dashSpace != oldDelegate._dashSpace ||
        _strokeWidth != oldDelegate._strokeWidth;
  }
}
Farrison answered 17/9, 2020 at 13:44 Comment(0)
D
0

Use dotted_line: ^3.0.0 lib which provides dashed lines and many more link

import 'package:dotted_line/dotted_line.dart';

DottedLine(
  direction: Axis.horizontal,
  lineLength: double.infinity,
  lineThickness: 1.0,
  dashLength: 4.0,
  dashColor: Colors.grey,
  dashRadius: 0.0,
  dashGapLength: 4.0,
  dashGapColor: Colors.transparent,
  dashGapRadius: 0.0,
)

Output:

enter image description here

Dank answered 26/5, 2021 at 18:0 Comment(0)
V
0
Container(
                  color: Colors.white,
                  height: 40.0,
                  child: Center(
                    child: Text(
                      "---------------------------------------------------------------------------",
                      maxLines: 1,
                      style: typoNormalTextRegular.copyWith(
                          color: colorABGray),
                    ),
                  ),
                ),

Only use Text Widget, easy solution

Voltaire answered 16/7, 2021 at 7:18 Comment(2)
are you serious?Lilybel
wild and creative idea! Nice!Entozoon
H
0
class dotWidget extends StatelessWidget {
  const dotWidget({super.key,});
  @override
  Widget build(BuildContext context) {
    return Row(
      children: List.generate(45, (index) {
        return Padding(
          padding: const EdgeInsets.only(left: 6.0),
          child: Container(height: 1, width: 1, color: Colors.grey.shade500),
        );
      }),
    );
  }
}

then call the widgets

Ho answered 22/11, 2023 at 4:52 Comment(0)
A
-1

To have horizontal dashed line I have made following custom class:

Custom Painter Class:

class DrawDottedhorizontalline extends CustomPainter {
  Paint _paint;
  DrawDottedhorizontalline() {
    _paint = Paint();
    _paint.color = Colors.black; //dots color
    _paint.strokeWidth = 2; //dots thickness
    _paint.strokeCap = StrokeCap.square; //dots corner edges
  }

  @override
  void paint(Canvas canvas, Size size) {
    for (double i = -300; i < 300; i = i + 15) {
      // 15 is space between dots
      if (i % 3 == 0)
        canvas.drawLine(Offset(i, 0.0), Offset(i + 10, 0.0), _paint);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

Use:

 Container(
               color: Colors.white,
                height: 150.0, //height of container
                child: Center(
                  child:CustomPaint(painter: DrawDottedhorizontalline()),
                  //drawing horizontal dotted/dash line          
                ),
            ),
Anodize answered 22/2, 2023 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.