Files
CityCards_Customer_Flutter/lib/common_packages/custom_dashed_line.dart

269 lines
7.9 KiB
Dart

import 'package:flutter/material.dart';
class DashedDivider extends StatelessWidget {
final double? height;
final double? thickness;
final double? indent;
final double? endIndent;
final Color? color;
final double dashLength;
final double dashSpace;
final double mainAxisOffset;
/// If true, shows the advanced pill-style dashed divider
final bool isAdvanced;
const DashedDivider({
super.key,
this.height,
this.thickness,
this.color,
this.indent,
this.endIndent,
this.dashLength = 5,
this.dashSpace = 5,
this.mainAxisOffset = 0.0,
this.isAdvanced = false,
}) : assert(height == null || height >= 0.0),
assert(thickness == null || thickness >= 0.0),
assert(indent == null || indent >= 0.0),
assert(endIndent == null || endIndent >= 0.0);
@override
Widget build(BuildContext context) {
// ── Advanced pill-style divider ──
if (isAdvanced) {
return _AdvancedDashedDivider(
color: color ?? const Color(0xFFBEBEBE),
height: height ?? 20,
indent: indent ?? 0,
endIndent: endIndent ?? 0,
);
}
// ── Original dashed divider ──
final theme = DividerThemeProvider.of(context).withDefaults(
height: height,
thickness: thickness,
indent: indent,
endIndent: endIndent,
color: color,
);
return Container(
margin: EdgeInsets.only(left: theme.indent, right: theme.endIndent),
height: theme.height,
width: double.infinity,
child: CustomPaint(
painter: DashedLinePainter(
color: theme.color,
thickness: theme.thickness,
dashLength: dashLength,
dashSpace: dashSpace,
mainAxisOffset: mainAxisOffset,
),
),
);
}
}
// ─────────────────────────────────────────────
// Advanced Pill-Style Dashed Divider
// ─────────────────────────────────────────────
class _AdvancedDashedDivider extends StatelessWidget {
final Color color;
final double height;
final double indent;
final double endIndent;
const _AdvancedDashedDivider({
required this.color,
required this.height,
required this.indent,
required this.endIndent,
});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: indent, right: endIndent),
height: height,
width: double.infinity,
child: CustomPaint(
painter: _PillDashedLinePainter(color: color),
),
);
}
}
class _PillDashedLinePainter extends CustomPainter {
final Color color;
_PillDashedLinePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..style = PaintingStyle.stroke
..strokeWidth = 1.5;
const pillWidth = 22.0;
const pillHeight = 10.0;
const gap = 6.0;
const radius = pillHeight / 2;
final centerY = size.height / 2;
double x = 0;
while (x + pillWidth <= size.width) {
final rect = RRect.fromRectAndRadius(
Rect.fromLTWH(x, centerY - radius, pillWidth, pillHeight),
const Radius.circular(radius),
);
canvas.drawRRect(rect, paint);
x += pillWidth + gap;
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
// ─────────────────────────────────────────────
// Original Painter
// ─────────────────────────────────────────────
class DashedLinePainter extends CustomPainter {
final Color color;
final double thickness;
final double dashLength;
final double dashSpace;
final bool isVertical;
final double mainAxisOffset;
DashedLinePainter({
required this.color,
required this.thickness,
required this.dashLength,
required this.dashSpace,
this.isVertical = false,
this.mainAxisOffset = 0.0,
});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..strokeWidth = thickness <= 0 ? 1 : thickness;
final mainAxisSize = _getMainAxisSize(size);
final crossAxisPosition = _getCrossAxisPosition(size);
canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height));
double currentPosition = mainAxisOffset;
while (currentPosition < mainAxisSize) {
double nextDashEnd = currentPosition + dashLength;
if (nextDashEnd > mainAxisSize) {
nextDashEnd = mainAxisSize;
}
final start = _calculateStartOffset(crossAxisPosition, currentPosition);
final end = _calculateEndOffset(crossAxisPosition, nextDashEnd);
canvas.drawLine(start, end, paint);
currentPosition += dashLength + dashSpace;
}
}
double _getMainAxisSize(Size size) =>
isVertical ? size.height : size.width;
double _getCrossAxisPosition(Size size) =>
isVertical ? size.width / 2 : size.height / 2;
Offset _calculateStartOffset(double crossAxisPosition, double currentPosition) =>
isVertical
? Offset(crossAxisPosition, currentPosition)
: Offset(currentPosition, crossAxisPosition);
Offset _calculateEndOffset(double crossAxisPosition, double nextDashEnd) =>
isVertical
? Offset(crossAxisPosition, nextDashEnd)
: Offset(nextDashEnd, crossAxisPosition);
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
// ─────────────────────────────────────────────
// Theme Provider (unchanged)
// ─────────────────────────────────────────────
class DividerThemeProvider {
final DividerThemeData _dividerTheme;
final ThemeData _theme;
final DividerThemeData _defaults;
double? _width;
double? _height;
double? _thickness;
double? _indent;
double? _endIndent;
Color? _color;
DividerThemeProvider._(BuildContext context)
: _dividerTheme = DividerTheme.of(context),
_theme = Theme.of(context),
_defaults = Theme.of(context).useMaterial3
? _DividerDefaultsM3(context)
: _DividerDefaultsM2(context);
static DividerThemeProvider of(BuildContext context) {
return DividerThemeProvider._(context);
}
DividerThemeProvider withDefaults({
double? width,
double? height,
double? thickness,
double? indent,
double? endIndent,
Color? color,
}) {
_width = width ?? _width;
_height = height ?? _height;
_thickness = thickness ?? _thickness;
_indent = indent ?? _indent;
_endIndent = endIndent ?? _endIndent;
_color = color ?? _color;
return this;
}
double get width => _width ?? _dividerTheme.space ?? _defaults.space!;
double get height => _height ?? _dividerTheme.space ?? _defaults.space!;
double get thickness => _thickness ?? _dividerTheme.thickness ?? _defaults.thickness!;
double get indent => _indent ?? _dividerTheme.indent ?? _defaults.indent!;
double get endIndent => _endIndent ?? _dividerTheme.endIndent ?? _defaults.endIndent!;
Color get color => _color ?? _dividerTheme.color ?? _defaults.color ?? _theme.dividerColor;
}
class _DividerDefaultsM3 extends DividerThemeData {
const _DividerDefaultsM3(this.context)
: super(space: 16, thickness: 1.0, indent: 0, endIndent: 0);
final BuildContext context;
@override
Color? get color => Theme.of(context).colorScheme.outlineVariant;
}
class _DividerDefaultsM2 extends DividerThemeData {
const _DividerDefaultsM2(this.context)
: super(space: 16, thickness: 0, indent: 0, endIndent: 0);
final BuildContext context;
@override
Color? get color => Theme.of(context).dividerColor;
}