Shreyansh Sharma
Shreyansh Sharma

Reputation: 1824

I want to change the color of focused otp text field's single element in flutter

In my OTP text field, the focused color of the bottom border of a single element, or textfield is blue by default. How can i change it to orange?? Also how can i change the unfocused color of that border from black to white. That is by default, without entering any number, color of all blocks or bottom border is white??? I will highlight the property in the image.

Check out this image, if you didn't understand properly that what i am trying to say - MobileImage

Here's the code -

import 'package:flutter/material.dart';
import 'package:otp_text_field/style.dart';

class OTPTextField extends StatefulWidget {
  /// Number of the OTP Fields
  final int length;

  /// Total Width of the OTP Text Field
  final double width;

  /// Width of the single OTP Field
  final double fieldWidth;

  /// Manage the type of keyboard that shows up
  TextInputType keyboardType;

  /// The style to use for the text being edited.
  final TextStyle style;

  /// Text Field Alignment
  /// default: MainAxisAlignment.spaceBetween [MainAxisAlignment]
  final MainAxisAlignment textFieldAlignment;

  /// Obscure Text if data is sensitive
  final bool obscureText;

  /// Text Field Style for field shape.
  /// default FieldStyle.underline [FieldStyle]
  final FieldStyle fieldStyle;

  /// Callback function, called when a change is detected to the pin.
  final ValueChanged<String> onChanged;

  /// Callback function, called when pin is completed.
  final ValueChanged<String> onCompleted;

  OTPTextField(
      {Key key,
      this.length = 4,
      this.width = 20,
      this.fieldWidth = 50,
      this.keyboardType = TextInputType.number,
      this.style = const TextStyle(),
      this.textFieldAlignment = MainAxisAlignment.spaceBetween,
      this.obscureText = false,
      this.fieldStyle = FieldStyle.underline,
      this.onChanged,
      this.onCompleted})
      : assert(length > 1);

  @override
  _OTPTextFieldState createState() => _OTPTextFieldState();
}

class _OTPTextFieldState extends State<OTPTextField> {
  List<FocusNode> _focusNodes;
  List<TextEditingController> _textControllers;

  List<Widget> _textFields;
  List<String> _pin;

  @override
  void initState() {
    super.initState();
    _focusNodes = List<FocusNode>(widget.length);
    _textControllers = List<TextEditingController>(widget.length);

    _pin = List.generate(widget.length, (int i) {
      return '';
    });
    _textFields = List.generate(widget.length, (int i) {
      return buildTextField(context, i);
    });
  }

  @override
  void dispose() {
    _textControllers
        .forEach((TextEditingController controller) => controller.dispose());
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      child: Row(
        mainAxisAlignment: widget.textFieldAlignment,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: _textFields,
      ),
    );
  }

  /// This function Build and returns individual TextField item.
  ///
  /// * Requires a build context
  /// * Requires Int position of the field
  Widget buildTextField(BuildContext context, int i) {
    if (_focusNodes[i] == null) _focusNodes[i] = new FocusNode();

    if (_textControllers[i] == null)
      _textControllers[i] = new TextEditingController();

    return Container(
      width: widget.fieldWidth,
      child: TextField(
        cursorColor: Colors.white,
        controller: _textControllers[i],
        keyboardType: widget.keyboardType,
        textAlign: TextAlign.center,
        maxLength: 1,
        style: widget.style,
        focusNode: _focusNodes[i],
        obscureText: true,
        decoration: InputDecoration(
          fillColor: Colors.white,
            counterText: "",
            border: widget.fieldStyle == FieldStyle.box
                ? OutlineInputBorder(borderSide: BorderSide(width: 4.0, color: Colors.green))
                : null),
        onChanged: (String str) {
          // Check if the current value at this position is empty
          // If it is move focus to previous text field.
          if (str.isEmpty) {
            if (i == 0) return;
            _focusNodes[i].unfocus();
            _focusNodes[i - 1].requestFocus();
          }

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

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

          String currentPin = "";
          _pin.forEach((String value) {
            currentPin += value;
          });

          // 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(currentPin);
          }

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

Upvotes: 1

Views: 4608

Answers (2)

Felix Runye
Felix Runye

Reputation: 2521

From the package here Easy fix is by adding the otpFieldStyle property and edit the colors as preferred for example:

  Padding(
        padding: EdgeInsets.only(top:18.0),
        child: OTPTextField(
          length: 4,
           width: MediaQuery.of(context).size.width,
           textFieldAlignment: MainAxisAlignment.spaceAround,
           fieldWidth: 55,
           fieldStyle: FieldStyle.underline,
           otpFieldStyle: OtpFieldStyle(
                  focusBorderColor: Colors.orange //(here)
           ),
           outlineBorderRadius: 15,
           style: TextStyle(fontSize: 17, color: Colors.white, ),
           onChanged: (pin) {
                  print("Changed: " + pin);
           },
           onCompleted: (pin) {
                  print("Completed: " + pin);
           }),
          ),

which has more properties as below

OtpFieldStyle(
  {this.backgroundColor: Colors.transparent,
  this.borderColor: Colors.black26,
  this.focusBorderColor: Colors.blue,
  this.disabledBorderColor: Colors.grey,
  this.enabledBorderColor: Colors.black26,
  this.errorBorderColor: Colors.red});

Upvotes: 0

CoderUni
CoderUni

Reputation: 6134

Your default Theme color is blue, this will be applied to your TextField. You would need to change your Theme color for your TextField to change your border color. Take note that this will only change the Theme color for TextField and not for your whole Flutter app.

child: Theme(
          data: ThemeData(
            primaryColor: Colors.orangeAccent,
            primaryColorDark: Colors.orange,
          ),
          child: TextField(
            ...
          ));

Upvotes: 1

Related Questions