Claude
Skills
Sign in
Back

flutter-core:flutter-forms-input

Included with Lifetime
$97 forever

Comprehensive guide to Flutter forms, validation, gestures, and input handling

Generalflutterformsvalidationgesturesinputfocuskeyboard

What this skill does


# Flutter Forms and Input Handling

Master Flutter's form system, validation strategies, gesture detection, and input management to create interactive, user-friendly applications.

## Overview

Flutter provides a comprehensive system for handling user input through forms, text fields, validation, gestures, and focus management. This skill covers the complete spectrum of input handling, from simple text fields to complex multi-step forms with validation, and from basic tap detection to custom gesture recognizers.

## When to Use This Skill

Use this skill when you need to:

- Build forms with validation
- Implement text input fields with proper state management
- Detect and respond to user gestures (tap, drag, swipe, scale)
- Manage keyboard focus and navigation
- Create custom input controls and validators
- Handle complex multi-step form flows
- Implement drag-and-drop functionality
- Respond to touch, mouse, or stylus input

## Core Concepts

### Form Architecture

Flutter's form system is built on several key components that work together:

**Form Widget**: The container that manages the state of multiple form fields. It uses a `GlobalKey<FormState>()` to access validation and submission methods.

**TextFormField**: The primary input widget for forms, integrating text input with validation. It automatically registers with parent Form widgets and participates in form-wide validation.

**FormState**: The state object that provides methods like `validate()`, `save()`, and `reset()`. Access it through the form's GlobalKey.

**Validators**: Functions that return error messages for invalid input or null for valid input.

### Gesture System

Flutter's gesture system operates on two layers:

**Pointer Events**: Raw data about touch, mouse, or stylus interactions (PointerDownEvent, PointerMoveEvent, PointerUpEvent, PointerCancelEvent).

**Gestures**: Semantic actions recognized from pointer events (taps, drags, scales, swipes).

The gesture system uses a competitive arena where multiple gesture recognizers compete to claim input events. This allows sophisticated gesture handling without conflicts.

### Focus Management

The focus system directs keyboard input to specific widgets:

**FocusNode**: A long-lived object that holds focus state for a widget. Must be created in State and disposed properly.

**FocusScope**: Groups focus nodes and manages focus history within a subtree.

**Focus Widget**: Owns and manages a FocusNode, providing callbacks for focus changes and key events.

## Form Implementation Patterns

### Basic Form Structure

```dart
class MyForm extends StatefulWidget {
  @override
  State<MyForm> createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
  final _formKey = GlobalKey<FormState>();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();

  @override
  void dispose() {
    _nameController.dispose();
    _emailController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
            controller: _nameController,
            decoration: InputDecoration(labelText: 'Name'),
            validator: (value) {
              if (value?.isEmpty ?? true) {
                return 'Name is required';
              }
              return null;
            },
          ),
          TextFormField(
            controller: _emailController,
            decoration: InputDecoration(labelText: 'Email'),
            validator: (value) {
              if (value?.isEmpty ?? true) {
                return 'Email is required';
              }
              if (!value!.contains('@')) {
                return 'Invalid email';
              }
              return null;
            },
          ),
          ElevatedButton(
            onPressed: () {
              if (_formKey.currentState!.validate()) {
                // Process form
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Processing...')),
                );
              }
            },
            child: Text('Submit'),
          ),
        ],
      ),
    );
  }
}
```

### Validation Strategies

**Synchronous Validation**: Immediate validation during user input or on submission. Used for format checking, required fields, and simple business rules.

**Asynchronous Validation**: Validation that requires external checks (API calls, database lookups). Implement with FutureBuilder or state management.

**Real-time vs On-Submit**: Choose `autovalidateMode` based on UX needs:
- `AutovalidateMode.disabled`: Validate only on submit (default)
- `AutovalidateMode.onUserInteraction`: Validate after first interaction
- `AutovalidateMode.always`: Validate on every change (can be annoying)

### State Management

Use `TextEditingController` to:
- Access current text value
- Listen for text changes
- Set text programmatically
- Clear fields

Always dispose controllers in the `dispose()` method to prevent memory leaks.

## Gesture Detection Patterns

### GestureDetector

```dart
GestureDetector(
  onTap: () => print('Tapped'),
  onDoubleTap: () => print('Double tapped'),
  onLongPress: () => print('Long pressed'),
  onPanUpdate: (details) {
    // Handle drag
    print('Delta: ${details.delta}');
  },
  child: Container(
    width: 200,
    height: 200,
    color: Colors.blue,
  ),
)
```

### InkWell for Material Effects

```dart
InkWell(
  onTap: () => print('Tapped with ripple'),
  splashColor: Colors.blue.withOpacity(0.3),
  child: Container(
    padding: EdgeInsets.all(16),
    child: Text('Tap me'),
  ),
)
```

### Gesture Conflicts

Avoid mixing conflicting gestures:
- Cannot use `onPanUpdate` with `onVerticalDragUpdate` or `onHorizontalDragUpdate`
- Gesture arena automatically resolves competition between multiple detectors
- Only callbacks that are non-null participate in gesture detection

## Focus and Keyboard Management

### FocusNode Lifecycle

```dart
class _MyWidgetState extends State<MyWidget> {
  late FocusNode _focusNode;

  @override
  void initState() {
    super.initState();
    _focusNode = FocusNode(debugLabel: 'MyWidget');
  }

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Focus(
      focusNode: _focusNode,
      onFocusChange: (focused) {
        setState(() {
          // Update UI based on focus
        });
      },
      child: TextField(),
    );
  }
}
```

### Focus Control

```dart
// Request focus
_focusNode.requestFocus();

// Remove focus
_focusNode.unfocus();

// Check focus state
bool hasFocus = _focusNode.hasFocus;

// Move to next field
FocusScope.of(context).nextFocus();

// Move to previous field
FocusScope.of(context).previousFocus();
```

### TextInputAction

Configure keyboard action buttons:

```dart
TextFormField(
  textInputAction: TextInputAction.next, // Shows "Next" button
  onFieldSubmitted: (value) {
    FocusScope.of(context).nextFocus(); // Move to next field
  },
)

TextFormField(
  textInputAction: TextInputAction.done, // Shows "Done" button
  onFieldSubmitted: (value) {
    FocusScope.of(context).unfocus(); // Close keyboard
  },
)
```

### Keyboard Types

```dart
TextFormField(
  keyboardType: TextInputType.emailAddress,
  // Other options: number, phone, url, datetime, text, multiline
)
```

## Best Practices

### Forms

1. **Always use GlobalKey**: Required for accessing FormState methods
2. **Dispose controllers**: Prevent memory leaks by disposing TextEditingController and FocusNode
3. **Provide clear feedback**: Show validation errors and submission states
4. **Handle loading states**: Disable submit buttons during processing
5. **Use TextFormField over TextField**: Better integration with Form widget
6. **Validate on submission first**: Avoid annoying users with premature validation

### Gestu

Related in General