drawPin method

  1. @override
void drawPin(
  1. Canvas canvas,
  2. Size size,
  3. String text,
  4. int pinLength,
  5. Cursor? cursor,
  6. TextDirection textDirection,
)
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,
    );
  }
}