floating_label_inputs 0.1.1
floating_label_inputs: ^0.1.1 copied to clipboard
A Flutter package providing highly customizable text input fields with animated floating labels, error states, and height clamping.
import 'package:flutter/material.dart';
import 'package:floating_label_inputs/floating_label_inputs.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Floating Label Input Demo',
theme: ThemeData(
brightness: Brightness.dark,
scaffoldBackgroundColor: const Color(0xFF1D2B3A),
colorScheme: ColorScheme.fromSwatch(brightness: Brightness.dark)
.copyWith(error: Colors.orangeAccent),
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _nameController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _companyEmailController =
TextEditingController(); // New controller
// FocusNodes are optional but good for managing focus programmatically
final FocusNode _nameFocusNode = FocusNode();
final FocusNode _emailFocusNode = FocusNode();
final FocusNode _companyEmailFocusNode = FocusNode(); // New FocusNode
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
_companyEmailController.dispose(); // Dispose new controller
_nameFocusNode.dispose();
_emailFocusNode.dispose();
_companyEmailFocusNode.dispose(); // Dispose new FocusNode
super.dispose();
}
void _submitForm() {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('Processing Data')));
print('Form is valid!');
print('Name: ${_nameController.text}');
print('Email: ${_emailController.text}');
print(
'Company Email: ${_companyEmailController.text}'); // Print new field
} else {
print('Form is invalid!');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Floating Label Demo App'),
backgroundColor: const Color(0xFF1D2B3A),
elevation: 0,
),
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(30.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingAnimatedInput(
labelText: 'Full Name',
controller: _nameController,
focusNode: _nameFocusNode,
textStyle: const TextStyle(color: Colors.white, fontSize: 16),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
if (value.length < 3) {
return 'Name must be at least 3 characters';
}
return null;
},
autovalidateMode: AutovalidateMode.onUserInteraction,
errorTextStyle: TextStyle(
color: Colors.yellow[700],
fontSize: 13,
fontWeight: FontWeight.bold),
errorBorderSide:
BorderSide(color: Colors.yellow[700]!, width: 1.5),
focusedErrorBorderSide:
BorderSide(color: Colors.yellow[900]!, width: 2.0),
),
const SizedBox(height: 20),
FloatingAnimatedInput(
labelText: 'Personal Email',
controller: _emailController,
focusNode: _emailFocusNode,
textStyle: const TextStyle(color: Colors.white, fontSize: 16),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
if (!emailRegex.hasMatch(value)) {
return 'Enter a valid email address';
}
return null;
},
autovalidateMode: AutovalidateMode.onUserInteraction,
),
const SizedBox(height: 20), // Added spacing
FloatingAnimatedInput(
// New field for Company Email
labelText: 'Company Email',
controller: _companyEmailController,
focusNode: _companyEmailFocusNode,
textStyle: const TextStyle(color: Colors.white, fontSize: 16),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your company email';
}
final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
if (!emailRegex.hasMatch(value)) {
return 'Enter a valid email address format';
}
const String requiredDomain = '@test.com';
if (!value.toLowerCase().endsWith(requiredDomain)) {
return 'Email must be from the $requiredDomain domain';
}
return null; // Valid
},
autovalidateMode: AutovalidateMode.onUserInteraction,
// You can customize error styles for this field too if needed
// errorTextStyle: TextStyle(color: Colors.cyanAccent, fontSize: 13),
// errorBorderSide: BorderSide(color: Colors.cyanAccent, width: 1.5),
),
const SizedBox(height: 30),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF00DFC4),
padding: const EdgeInsets.symmetric(
horizontal: 50, vertical: 15),
textStyle:
const TextStyle(fontSize: 16, color: Color(0xFF1D2B3A)),
),
onPressed: _submitForm,
child: const Text('Submit',
style: TextStyle(color: Color(0xFF1D2B3A))),
),
const SizedBox(height: 40),
FloatingAnimatedInput(
labelText: 'Square TextField',
textFieldBorderRadius: BorderRadius.circular(0),
),
const SizedBox(height: 30),
FloatingAnimatedInput(
labelText: 'Rounded TextField',
textFieldBorderRadius: BorderRadius.circular(25.0),
height: 45,
)
],
),
),
),
),
);
}
}