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 underlinePaint = Paint()
..strokeWidth = lineHeight
..style = PaintingStyle.stroke
..isAntiAlias = true;
if (lineStrokeCap != null) {
underlinePaint.strokeCap = lineStrokeCap!;
}
/// Assign paint if [bgColorBuilder] is not null
Paint? insidePaint;
if (bgColorBuilder != null) {
insidePaint = Paint()
..style = PaintingStyle.fill
..isAntiAlias = true;
}
var startX = 0.0;
var startY = mainHeight - lineHeight;
double gapTotalLength =
gapSpaces?.reduce((a, b) => a + b) ?? (pinLength - 1) * gapSpace;
List<double> actualGapSpaces =
gapSpaces ?? List.filled(pinLength - 1, gapSpace);
/// Calculate the width of each underline.
double singleWidth = (size.width - gapTotalLength) / pinLength;
for (int i = 0; i < pinLength; i++) {
if (errorText != null && errorText!.isNotEmpty) {
/// only draw error-color as underline-color if errorText is not null
underlinePaint.color =
errorTextStyle?.color ?? colorBuilder.indexProperty(i);
} else {
underlinePaint.color = colorBuilder.indexProperty(i);
}
canvas.drawLine(Offset(startX, startY),
Offset(startX + singleWidth, startY), underlinePaint);
if (insidePaint != null) {
canvas.drawRect(
Rect.fromLTWH(startX, 0, singleWidth, startY - lineHeight / 2),
insidePaint..color = bgColorBuilder!.indexProperty(i));
}
startX += singleWidth + (i == pinLength - 1 ? 0 : actualGapSpaces[i]);
}
/// The char index of the [text]
var index = 0;
startX = 0.0;
startY = 0.0;
/// Determine whether display obscureText.
bool obscureOn = obscureStyle != null && obscureStyle!.isTextObscure;
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;
}
startX = singleWidth * index +
singleWidth / 2 -
textPainter.width / 2 +
actualGapSpaces.take(index).sumList();
textPainter.paint(canvas, Offset(startX, 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;
startX = singleWidth * index +
singleWidth / 2 -
textPainter.width / 2 +
actualGapSpaces.take(index).sumList();
textPainter.paint(canvas, Offset(startX, startY));
index++;
});
}
/// Draw the cursor if provided.
if (cursor != null && cursor.enabled && cursorIndex < pinLength) {
drawCursor(
canvas,
size,
Rect.fromLTWH(
singleWidth * cursorIndex +
actualGapSpaces.take(cursorIndex).sumList(),
0,
singleWidth,
size.height,
),
cursor,
cursorOffset,
textDirection,
);
}
}