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 borderPaint = Paint()
    ..color = strokeColor
    ..strokeWidth = strokeWidth
    ..style = PaintingStyle.stroke
    ..isAntiAlias = true;

  /// Assign paint if [solidColor] is not null
  Paint? insidePaint;
  if (bgColorBuilder != null) {
    insidePaint = Paint()
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.fill
      ..isAntiAlias = true;
  }

  Rect rect = Rect.fromLTRB(
    strokeWidth / 2,
    strokeWidth / 2,
    size.width - strokeWidth / 2,
    mainHeight - strokeWidth / 2,
  );

  /// Draw the whole rect.
  canvas.drawRRect(RRect.fromRectAndRadius(rect, radius), borderPaint);

  /// Calculate the width of each underline.
  double singleWidth =
      (size.width - strokeWidth * (pinLength + 1)) / pinLength;

  for (int i = 0; i < pinLength; i++) {
    if (insidePaint != null) {
      var corners = _getCorner(i, pinLength);
      canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromLTWH(
            singleWidth * i + strokeWidth * (i + 1),
            strokeWidth,
            singleWidth,
            mainHeight - strokeWidth * 2,
          ),
          topLeft: corners[0],
          topRight: corners[1],
          bottomRight: corners[2],
          bottomLeft: corners[3],
        ),
        insidePaint..color = bgColorBuilder!.indexProperty(i),
      );
    }
    if (i == 0) continue;
    double offsetX = singleWidth +
        strokeWidth * i +
        strokeWidth / 2 +
        singleWidth * (i - 1);
    canvas.drawLine(Offset(offsetX, strokeWidth),
        Offset(offsetX, mainHeight - strokeWidth), borderPaint);
  }

  /// The char index of the [text]
  var index = 0;
  var startY = 0.0;
  var startX = 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 = strokeWidth * (index + 1) +
        singleWidth * index +
        singleWidth / 2 -
        textPainter.width / 2;
    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 = strokeWidth * (index + 1) +
          singleWidth * index +
          singleWidth / 2 -
          textPainter.width / 2;
      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 + strokeWidth * cursorIndex,
        0,
        singleWidth,
        size.height,
      ),
      cursor,
      cursorOffset,
      textDirection,
    );
  }
}