buildTextField method

Widget buildTextField(
  1. BuildContext context,
  2. int index
)

This function Build and returns individual TextField item.

  • Requires a build context
  • Requires Int position of the field

Implementation

Widget buildTextField(BuildContext context, int index) {
  FocusNode? focusNode = _focusNodes[index];
  TextEditingController? textEditingController = _textControllers[index];

  // if focus node doesn't exist, create it.
  if (focusNode == null) {
    _focusNodes[index] = FocusNode();
    focusNode = _focusNodes[index];
    focusNode?.addListener((() => handleFocusChange(index)));
  }
  if (textEditingController == null) {
    _textControllers[index] = TextEditingController();
    textEditingController = _textControllers[index];
  }

  final isLast = index == widget.length - 1;

  InputBorder getBorder(Color color) {
    final colorOrError =
        widget.hasError ? _otpFieldStyle.errorBorderColor : color;

    return widget.fieldStyle == FieldStyle.box
        ? OutlineInputBorder(
            borderSide: BorderSide(color: colorOrError),
            borderRadius: BorderRadius.circular(widget.outlineBorderRadius),
          )
        : UnderlineInputBorder(borderSide: BorderSide(color: colorOrError));
  }

  return Container(
    width: widget.fieldWidth,
    margin: EdgeInsets.only(
      right: isLast ? 0 : widget.spaceBetween,
    ),
    child: TextField(
      controller: _textControllers[index],
      keyboardType: widget.keyboardType,
      textCapitalization: widget.textCapitalization,
      textAlign: TextAlign.center,
      style: widget.style,
      inputFormatters: widget.inputFormatter,
      maxLength: 1,
      focusNode: _focusNodes[index],
      obscureText: widget.obscureText,
      decoration: InputDecoration(
        isDense: widget.isDense,
        filled: true,
        fillColor: _otpFieldStyle.backgroundColor,
        counterText: "",
        contentPadding: widget.contentPadding,
        border: getBorder(_otpFieldStyle.borderColor),
        focusedBorder: getBorder(_otpFieldStyle.focusBorderColor),
        enabledBorder: getBorder(_otpFieldStyle.enabledBorderColor),
        disabledBorder: getBorder(_otpFieldStyle.disabledBorderColor),
        errorBorder: getBorder(_otpFieldStyle.errorBorderColor),
        focusedErrorBorder: getBorder(_otpFieldStyle.errorBorderColor),
        errorText: null,
        // to hide the error text
        errorStyle: const TextStyle(height: 0, fontSize: 0),
      ),
      onChanged: (String str) {
        if (str.length > 1) {
          _handlePaste(str);
          return;
        }

        // Check if the current value at this position is empty
        // If it is move focus to previous text field.
        if (str.isEmpty) {
          if (index == 0) return;
          _focusNodes[index]!.unfocus();
          _focusNodes[index - 1]!.requestFocus();
        }

        // Update the current pin
        setState(() {
          _pin[index] = str;
        });

        // Remove focus
        if (str.isNotEmpty) _focusNodes[index]!.unfocus();
        // Set focus to the next field if available
        if (index + 1 != widget.length && str.isNotEmpty) {
          FocusScope.of(context).requestFocus(_focusNodes[index + 1]);
        }

        String currentPin = _getCurrentPin();

        // if there are no null values that means otp is completed
        // Call the `onCompleted` callback function provided
        if (!_pin.contains(null) &&
            !_pin.contains('') &&
            currentPin.length == widget.length) {
          widget.onCompleted?.call(currentPin);
        }

        // Call the `onChanged` callback function
        widget.onChanged!(currentPin);
      },
    ),
  );
}