drawPin method
void
drawPin()
override
Implementation
@override
void drawPin(
Canvas canvas,
Size size,
String text,
int pinLength,
Cursor? cursor,
TextDirection textDirection,
) {
/// Calculate the height of paint area for drawing the pin field.
/// it should honor the error text (if any) drawn by
/// the actual texfield behind.
/// but, since we can access the drawn textfield behind from here,
/// we use a simple logic to calculate it.
double mainHeight;
if (errorText != null && errorText!.isNotEmpty) {
mainHeight = size.height - (errorTextStyle?.fontSize ?? 0 + 8.0);
} else {
mainHeight = size.height;
}
Paint borderPaint = Paint()
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke
..isAntiAlias = true;
/// Assign paint if [solidColor] is not null
Paint? insidePaint;
if (bgColorBuilder != null) {
insidePaint = Paint()
..style = PaintingStyle.fill
..isAntiAlias = true;
}
double gapTotalLength = gapSpaces?.sumList() ?? (pinLength - 1) * gapSpace;
/// Calculate the width of each digit include stroke.
double singleWidth =
(size.width - strokeWidth - gapTotalLength) / pinLength;
double radius; // include strokeWidth
List<double> actualGapSpaces;
if (singleWidth / 2 < mainHeight / 2 - strokeWidth / 2) {
radius = singleWidth / 2;
actualGapSpaces =
gapSpaces == null ? List.filled(pinLength - 1, gapSpace) : gapSpaces!;
} else {
radius = mainHeight / 2 - strokeWidth / 2;
actualGapSpaces = List.filled(
pinLength - 1,
(size.width - strokeWidth - radius * 2 * pinLength) /
(pinLength - 1));
}
double startX = strokeWidth / 2;
double startY = mainHeight / 2;
List<double> centerPoints = List.filled(pinLength, 0.0);
/// Draw the each shape of pin.
for (int i = 0; i < pinLength; i++) {
if (errorText != null && errorText!.isNotEmpty) {
/// only draw error-color as border-color or solid-color
/// if errorText is not null
borderPaint.color =
errorTextStyle?.color ?? strokeColorBuilder.indexProperty(i);
} else {
borderPaint.color = strokeColorBuilder.indexProperty(i);
}
centerPoints[i] = startX + radius;
canvas.drawCircle(
Offset(centerPoints[i], startY),
radius,
borderPaint,
);
if (insidePaint != null) {
canvas.drawCircle(
Offset(startX + radius, startY),
radius - strokeWidth / 2,
insidePaint..color = bgColorBuilder!.indexProperty(i),
);
}
startX += (radius * 2 + (i == pinLength - 1 ? 0 : actualGapSpaces[i]));
}
/// The char index of the [text]
var index = 0;
startY = 0.0;
/// Determine whether display obscureText.
bool obscureOn = obscureStyle?.isTextObscure == true;
TextPainter textPainter;
for (var rune in text.runes) {
String code;
if (obscureOn) {
code = obscureStyle!.obscureText;
} else {
code = String.fromCharCode(rune);
}
textPainter = TextPainter(
text: TextSpan(
style: textStyle,
text: code,
),
textAlign: TextAlign.center,
textDirection: textDirection,
);
/// Layout the text.
textPainter.layout();
/// No need to compute again
if (startY == 0.0) {
startY = mainHeight / 2 - textPainter.height / 2;
}
textPainter.paint(
canvas,
Offset(
centerPoints[index] - textPainter.width / 2,
startY,
));
index++;
}
/// Setup the cursor.
final int cursorIndex = index;
Offset? cursorOffset;
/// Fill the remaining space with hint text.
if (hintText != null) {
hintText!.substring(index).runes.forEach((rune) {
String code = String.fromCharCode(rune);
textPainter = TextPainter(
text: TextSpan(
style: hintTextStyle,
text: code,
),
textAlign: TextAlign.center,
textDirection: textDirection,
);
/// Layout the text.
textPainter.layout();
/// Save the size of the first hint text to offset the cursor.
if (index == cursorIndex) {
cursorOffset = Offset(textPainter.size.width / 2, 0);
}
startY = mainHeight / 2 - textPainter.height / 2;
textPainter.paint(canvas,
Offset(centerPoints[index] - textPainter.width / 2, startY));
index++;
});
}
/// Draw the cursor if provided.
if (cursor != null && cursor.enabled && cursorIndex < pinLength) {
drawCursor(
canvas,
size,
Rect.fromLTWH(
radius * cursorIndex * 2 +
actualGapSpaces.take(cursorIndex).sumList(),
0,
radius * 2,
size.height,
),
cursor,
cursorOffset,
textDirection,
);
}
}