I am trying to implement two related fields in a form using Riverpod in Flutter. The first field is a segmented class type selection, and the second is a text field for entering a custom class type. I need that when selecting a value from a segmented list, the input field is cleared, and vice versa — if a value is entered in the input field, it should reset the selection from the segmented list.
If I enter a value in a custom field, the selection is removed from the button. But by selecting the button, the custom field is not cleared, although it is strange.
import 'package:flutter/material.dart';import 'package:flutter_riverpod/flutter_riverpod.dart';void main() { runApp( const ProviderScope(child: MyApp()), );}class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Segmented Button and TextFormField')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ // SizedBox( width: double.infinity, child: Consumer( builder: (context, ref, child) { final lessonState = ref.watch(lessonControllerProvider); return SegmentedButton<String>( showSelectedIcon: false, emptySelectionAllowed: true, style: SegmentedButton.styleFrom( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(4)), ), ), segments: [ LessonSegment(value: '1', text: '1'), LessonSegment(value: '2', text: '2'), LessonSegment(value: '3', text: '3'), ], selected: {lessonState.lessonType}, onSelectionChanged: (Set<String> value) { if (value.isNotEmpty) { final selectedValue = value.first; ref .read(lessonControllerProvider.notifier) .updateField('lessonType', selectedValue); } }, ); }, ), ), const SizedBox(height: 8), // Consumer( builder: (context, ref, child) { final lessonState = ref.watch(lessonControllerProvider); return TextFormField( textAlign: TextAlign.center, initialValue: lessonState.customLessonType, decoration: InputDecoration( border: const OutlineInputBorder(), hintText: 'custom', hintStyle: Theme.of(context).textTheme.labelLarge, errorMaxLines: 2, ), onChanged: (value) { ref .read(lessonControllerProvider.notifier) .updateField('customLessonType', value); }, validator: (value) { if ((lessonState.lessonType.isEmpty && (value == null || value.isEmpty)) || (lessonState.lessonType.isNotEmpty && value?.isNotEmpty == true)) { return 'error'; } return null; }, ); }, ), ], ), ), ), ); }}class LessonState { final String lessonType; final String customLessonType; LessonState({ this.lessonType = '', this.customLessonType = '', }); LessonState copyWith({ String? lessonType, String? customLessonType, }) { return LessonState( lessonType: lessonType ?? this.lessonType, customLessonType: customLessonType ?? this.customLessonType, ); }}class LessonController extends StateNotifier<LessonState> { LessonController() : super(LessonState()); void updateField(String field, String value) { switch (field) { case 'lessonType': state = state.copyWith(lessonType: value, customLessonType: ''); break; case 'customLessonType': state = state.copyWith(customLessonType: value, lessonType: ''); break; } }}final lessonControllerProvider = StateNotifierProvider<LessonController, LessonState>( (ref) => LessonController(),);class LessonSegment extends ButtonSegment<String> { LessonSegment({required super.value, required String text}) : super( label: Padding( padding: const EdgeInsets.symmetric(vertical: 14.0), child: Text(text), ), );}