1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Positioning Validator Message Outside of Border in Custom TextFormField in Flutter

Discussão em 'Mobile' iniciado por Stack, Outubro 4, 2024 às 05:12.

  1. Stack

    Stack Membro Participativo

    am developing a Flutter application and using a CustomTextFormField widget to handle user input. However, I am facing an issue with the validator message appearing inside the border of the field, and I want to position it outside the border.

    Here is a snippet of the CustomTextFormField widget that I created:

    import 'package:flutter/material.dart';

    class CustomTextFormField extends StatefulWidget {
    final String label;
    final String? Function(String?)? validator;
    final void Function(String?)? onSaved;
    final TextEditingController? controller;
    final String? type;
    final TextInputType keyboardType;
    final IconData? suffixIcon;
    final IconData? prefixIcon;
    final bool isPassword; // Menambahkan parameter untuk kolom password
    final bool giveBorder;
    final bool isRequired;

    const CustomTextFormField({
    super.key,
    required this.label,
    required this.validator,
    this.controller,
    required this.type,
    required this.keyboardType,
    required this.onSaved,
    this.suffixIcon,
    this.prefixIcon,
    this.isPassword = false, // Default tidak menggunakan password
    this.giveBorder = false,
    this.isRequired = false,
    });
    @override
    State<CustomTextFormField> createState() {
    return _CustomTextFormFieldState();
    }
    }

    class _CustomTextFormFieldState extends State<CustomTextFormField> {
    bool _obscureText = true; // Mengatur visibilitas password

    @override
    Widget build(BuildContext context) {
    Widget content = Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    widget.isRequired
    ? Row(
    children: [
    Text(
    widget.label,
    style: const TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w600,
    color: Colors.black54,
    ),
    textAlign: TextAlign.start,
    ),
    const Text(
    ' *',
    style: TextStyle(color: Colors.red),
    )
    ],
    )
    : Text(
    widget.label,
    style: const TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w600,
    color: Colors.black54,
    ),
    textAlign: TextAlign.start,
    ),
    widget.giveBorder
    ? Container(
    margin: const EdgeInsets.symmetric(vertical: 8),
    padding: const EdgeInsets.symmetric(horizontal: 16),
    decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(10),
    border:
    Border.all(color: Colors.black12), // Border warna abu-abu
    ),
    child: TextField(
    controller: widget.controller,
    keyboardType: widget.keyboardType,
    obscureText: widget.isPassword ? _obscureText : false,
    decoration: InputDecoration(
    border: InputBorder.none, // Hilangkan border default
    hintText: widget.label, // Placeholder
    hintStyle: const TextStyle(color: Colors.grey),
    prefixIcon: widget.prefixIcon != null
    ? Icon(widget.prefixIcon)
    : null,
    suffixIcon:
    widget.isPassword // Menambahkan ikon untuk password
    ? IconButton(
    icon: Icon(
    _obscureText
    ? Icons
    .visibility_off // Tampilkan ikon 'lihat'
    : Icons
    .visibility, // Tampilkan ikon 'sembunyikan'
    ),
    onPressed: () {
    setState(() {
    _obscureText =
    !_obscureText; // Toggle visibilitas
    });
    },
    )
    : widget.suffixIcon != null
    ? Icon(widget.suffixIcon)
    : null,
    ),
    ),
    )
    : TextField(
    controller: widget.controller,
    keyboardType: widget.keyboardType,
    obscureText: widget.isPassword ? _obscureText : false,
    decoration: InputDecoration(
    hintText: widget.label, // Placeholder
    hintStyle: const TextStyle(color: Colors.grey),
    prefixIcon: widget.prefixIcon != null
    ? Icon(widget.prefixIcon)
    : null,
    suffixIcon: widget
    .isPassword // Menambahkan ikon untuk password
    ? IconButton(
    icon: Icon(
    _obscureText
    ? Icons.visibility_off // Tampilkan ikon 'lihat'
    : Icons
    .visibility, // Tampilkan ikon 'sembunyikan'
    ),
    onPressed: () {
    setState(() {
    _obscureText =
    !_obscureText; // Toggle visibilitas
    });
    },
    )
    : widget.suffixIcon != null
    ? Icon(widget.suffixIcon)
    : null,
    ),
    ),
    ],
    );

    if (widget.type == 'form') {
    content = Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    widget.isRequired
    ? Row(
    children: [
    Text(
    widget.label,
    style: const TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w600,
    color: Colors.black54,
    ),
    textAlign: TextAlign.start,
    ),
    const Text(
    ' *',
    style: TextStyle(color: Colors.red),
    )
    ],
    )
    : Text(
    widget.label,
    style: const TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w600,
    color: Colors.black54,
    ),
    textAlign: TextAlign.start,
    ),
    Container(
    alignment: Alignment.center,
    margin: const EdgeInsets.symmetric(vertical: 8),
    padding: EdgeInsets.only(
    right: 4,
    left: widget.prefixIcon != null ? 4 : 16,
    ),
    decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(10),
    border: widget.giveBorder
    ? Border.all(color: Colors.grey)
    : Border.all(color: Colors.black12), // Border warna abu-abu
    ),
    child: TextFormField(
    controller: widget.controller,
    keyboardType: widget.keyboardType,
    obscureText: widget.isPassword ? _obscureText : false,
    decoration: InputDecoration(
    border: InputBorder.none, // Hilangkan border default
    hintText: widget.label, // Placeholder
    hintStyle: const TextStyle(color: Colors.grey),
    prefixIcon:
    widget.prefixIcon != null ? Icon(widget.prefixIcon) : null,
    contentPadding: widget.isPassword
    ? const EdgeInsets.symmetric(vertical: 12)
    : null,
    suffixIcon: widget.isPassword // Menambahkan ikon untuk password
    ? IconButton(
    icon: Icon(
    _obscureText
    ? Icons.visibility_off
    : Icons.visibility,
    ),
    padding: EdgeInsets.zero,
    iconSize: 20,
    onPressed: () {
    setState(() {
    _obscureText = !_obscureText;
    });
    },
    )
    : widget.suffixIcon != null
    ? Icon(widget.suffixIcon)
    : null,
    ),
    onSaved: widget.onSaved,
    validator: widget.validator,
    ),
    ),
    ],
    );
    }

    return content;
    }
    }


    However, when validation fails, the error message appears inside the border of the TextFormField, as seen in the image below:

    I would like to know how to move the validator message to appear outside the border, so it does not interfere with the input appearance. Is there a recommended way to achieve this? Thank you in advance[​IMG]

    I want the validator on outside of border

    Continue reading...

Compartilhe esta Página