any_field 0.1.0
any_field: ^0.1.0 copied to clipboard
A flexible Flutter input field widget that can display arbitrary content while maintaining the look and feel of a TextField.
AnyField #
A flexible Flutter input field widget that can display arbitrary content while maintaining the look and feel of a TextField. Particularly well-suited for building custom picker fields that open dialogs for selection (date pickers, color pickers, multi-select, etc.).
Demo #
[AnyField demo]
Perfect for Dialog-based Pickers #
AnyField is designed to be the foundation for custom picker widgets that use dialogs or bottom sheets:
- Keep TextField's visual style (labels, borders, icons) while displaying any content
- Built-in tap handling for opening dialogs
- Easy integration with existing picker dialogs (DatePicker, ColorPicker, etc.)
- Support for async operations when selecting values
- Form-enabled wrapper for validation
Common use cases:
- Date/Time pickers with custom formats
- Multi-select fields with chip display
- Color pickers with preview
- Custom dropdown alternatives
- Any picker that needs dialog interaction
Quick links #
- AnyField โ main widget documentation and API
- AnyFormField / Form Integration โ form wrapper, usage and API
Features #
- ๐ Display any custom content within an input field
- ๐จ Full support for InputDecoration (labels, borders, icons)
- ๐ Configurable height constraints with scroll support
- ๐ Value management through controller pattern
- ๐ฑ๏ธ Tap handling for custom interaction
- โจ๏ธ Keyboard navigation support
any_field Changelog #
v0.1.0 โ InputDecorator Refactor & Alignment Reset #
Released: November 4, 2025
โจ Major Changes
-
Migrated core layout to
InputDecorator
Replaced legacy composition with nativeInputDecoratorfor idiomatic form field rendering and label/hint behavior. -
Removed all
compensationanddisplayPaddingparameters
Simplified API surface by eliminating manual layout overrides. Alignment now follows native Flutter behavior. -
Introduced baseline-driven hint alignment strategy
Hint text alignment now respects child baseline. Developers should ensure children provide valid baselines (e.g.Text,Baseline) for proper vertical centering.
๐งฑ Architectural Improvements
- Unified field rendering logic across dropdowns, text fields, and custom inputs.
- Improved compatibility with form validation, focus traversal, and accessibility.
- Reduced layout bugs related to padding compensation and vertical drift.
๐งช Migration Notes
- If your field previously relied on
displayPaddingorcompensation, you may need to adjust child height or wrap inBaselineto preserve hint alignment. - For tall fields (e.g. height โฅ 100), use
Text(' ')orBaselineinsideInputDecoratorto center hint text.
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
any_field: ^0.0.1
Usage #
Basic Example #
AnyField<List<String>>(
displayBuilder: (context, tags) => Wrap(
spacing: 4,
children: tags.map((tag) => Chip(label: Text(tag))).toList(),
),
controller: AnyValueController(['flutter', 'widget']),
decoration: InputDecoration(
labelText: 'Tags',
border: OutlineInputBorder(),
),
onTap: (current) => _showTagSelector(),
)
With Controller #
final controller = AnyValueController<DateTime>(
DateTime.now(),
shouldNotify: (prev, curr) => prev.day != curr.day,
);
AnyField<DateTime>(
displayBuilder: (context, date) => Text(
DateFormat.yMMMd().format(date),
),
controller: controller,
decoration: InputDecoration(
labelText: 'Date',
suffixIcon: Icon(Icons.calendar_today),
),
onTap: (current) async {
final date = await showDatePicker(...);
if (date != null) controller.value = date;
},
)
Usage notes #
- AnyField
onTapacceptsFutureOr<void>handlers. For AnyField the callback should update the controller (the return value is ignored). Example:
AnyField<DateTime>(
displayBuilder: (c, date) => Text(date == null ? 'Pick a date' : DateFormat.yMMMd().format(date)),
controller: controller,
onTap: (current) async {
final picked = await showDatePicker(...);
if (picked != null) controller.value = picked;
},
)
- AnyField is well suited for building picker UI that opens dialogs (date picker, selection dialogs, color pickers, etc.). Use the
onTapcallback to open your dialog and update the controller when the user selects a value.
API Reference #
AnyField #
| Parameter | Type | Description |
|---|---|---|
displayBuilder |
Widget Function(BuildContext, T) |
Builds the content display |
decoration |
InputDecoration |
Standard input decoration |
minHeight |
double? |
Minimum field height |
maxHeight |
double? |
Maximum field height |
controller |
AnyValueController<T>? |
Value controller |
onChanged |
ValueChanged<T?>? |
Value change callback |
onTap |
FutureOr<void> Function(T? value)? |
Tap handler (sync or async). Handler should update controller; return value is ignored. |
AnyValueController #
Controller for managing field values.
// Create with initial value
final controller = AnyValueController<int>(42);
// Create empty
final controller = AnyValueController<String>.empty();
// With custom change detection
final controller = AnyValueController<List>(
[],
shouldNotify: (prev, curr) => prev.length != curr.length,
);
Form Integration #
AnyField can be used within forms using the AnyFormField wrapper. Note: AnyFormField.onTap uses the same signature as AnyField (FutureOr<void> Function(T? value)?) โ the callback should update the controller or call onChanged to apply the selected value.
final controller = AnyValueController<DateTime?>(null);
Form(
key: _formKey,
child: Column(
children: [
AnyFormField<DateTime?>(
controller: controller,
displayBuilder: (context, date) =>
Text(date == null ? 'Pick a date' : DateFormat.yMMMd().format(date)),
decoration: InputDecoration(
labelText: 'Event Date',
suffixIcon: Icon(Icons.calendar_today),
),
validator: (value) {
if (value == null) return 'Please select a date';
if (value!.isBefore(DateTime.now())) {
return 'Date must be in the future';
}
return null;
},
onSaved: (value) => _eventDate = value,
onTap: (currentDate) async {
final date = await showDatePicker(
context: context,
initialDate: currentDate ?? DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2025),
);
if (date != null) {
controller.value = date;
}
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// Handle saved data
}
},
child: Text('Submit'),
),
],
),
)
AnyFormField API #
| Parameter | Type | Description |
|---|---|---|
displayBuilder |
Widget Function(BuildContext, T) |
Builds the content display |
decoration |
InputDecoration |
Input decoration (shows validation errors) |
minHeight |
double? |
Minimum field height |
maxHeight |
double? |
Maximum field height |
initialValue |
T? |
Initial value when no controller provided |
controller |
AnyValueController<T>? |
Optional external controller |
validator |
FormFieldValidator<T>? |
Form validation function |
onSaved |
FormFieldSetter<T>? |
Called when form is saved |
onChanged |
ValueChanged<T?>? |
Value change callback |
onTap |
FutureOr<void> Function(T? value)? |
Tap handler (sync or async). Handler should update controller or call onChanged. |
Additional Information #
- Works with any value type through generics
- Supports keyboard focus and navigation
- Automatically handles scroll when content exceeds maxHeight
- Compatible with Form widgets and validation
License #
MIT License - see the LICENSE file for details