@@ -56,6 +56,8 @@ class _ColorBottomSheetState extends State<_ColorBottomSheet> with SingleTickerP
5656 late final TabController _tabController;
5757 late final TextEditingController _customColorValueController;
5858
59+ int currentIndex = 0 ;
60+
5961 String ? _customTabErrorText;
6062
6163 Color _advancedTabColor = Colors .transparent;
@@ -64,6 +66,15 @@ class _ColorBottomSheetState extends State<_ColorBottomSheet> with SingleTickerP
6466
6567 List <Color > _recentCustomColors = [];
6668
69+ void onCurrentIndexChanged () {
70+ if (_tabController.indexIsChanging) {
71+ final newIndex = _tabController.index;
72+ setState (() {
73+ currentIndex = newIndex;
74+ });
75+ }
76+ }
77+
6778 void _updateCustomColorPreview (String ? v) {
6879 final tr = context.t.colorPickerDialog.tabs.custom;
6980
@@ -109,114 +120,106 @@ class _ColorBottomSheetState extends State<_ColorBottomSheet> with SingleTickerP
109120 Widget _buildAdvancedTab () {
110121 final tr = context.t.colorPickerDialog.tabs.advanced;
111122
112- return Column (
113- children: [
114- Expanded (
115- child: SingleChildScrollView (
116- child: ColorPicker (
117- padding: EdgeInsets .zero,
118- // Use the dialogPickerColor as start and active color.
119- color: _advancedTabColor,
120- // Update the dialogPickerColor using the callback.
121- onColorChanged: (color) => setState (() => _advancedTabColor = color),
122- borderRadius: 15 ,
123- spacing: 5 ,
124- runSpacing: 5 ,
125- wheelDiameter: 155 ,
126- heading: Text (tr.selectColor, style: Theme .of (context).textTheme.titleSmall),
127- subheading: Text (tr.selectColorShade, style: Theme .of (context).textTheme.titleSmall),
128- showMaterialName: true ,
129- showColorName: true ,
130- showColorCode: true ,
131- copyPasteBehavior: const ColorPickerCopyPasteBehavior (longPressMenu: true ),
132- materialNameTextStyle: Theme .of (context).textTheme.bodySmall,
133- colorNameTextStyle: Theme .of (context).textTheme.bodySmall,
134- colorCodeTextStyle: Theme .of (context).textTheme.bodySmall,
135- pickersEnabled: const < ColorPickerType , bool > {
136- ColorPickerType .both: true ,
137- ColorPickerType .primary: false ,
138- ColorPickerType .accent: false ,
139- ColorPickerType .bw: false ,
140- ColorPickerType .custom: false ,
141- ColorPickerType .customSecondary: false ,
142- ColorPickerType .wheel: false ,
143- },
144- showEditIconButton: true ,
145- // customColorSwatchesAndNames: colorsNameMap,
146- ),
123+ return Align (
124+ child: Column (
125+ mainAxisSize: .min,
126+ children: [
127+ ColorPicker (
128+ padding: EdgeInsets .zero,
129+ // Use the dialogPickerColor as start and active color.
130+ color: _advancedTabColor,
131+ // Update the dialogPickerColor using the callback.
132+ onColorChanged: (color) => setState (() => _advancedTabColor = color),
133+ borderRadius: 15 ,
134+ spacing: 5 ,
135+ runSpacing: 5 ,
136+ wheelDiameter: 155 ,
137+ heading: Text (tr.selectColor, style: Theme .of (context).textTheme.titleSmall),
138+ subheading: Text (tr.selectColorShade, style: Theme .of (context).textTheme.titleSmall),
139+ showMaterialName: true ,
140+ showColorName: true ,
141+ showColorCode: true ,
142+ copyPasteBehavior: const ColorPickerCopyPasteBehavior (longPressMenu: true ),
143+ materialNameTextStyle: Theme .of (context).textTheme.bodySmall,
144+ colorNameTextStyle: Theme .of (context).textTheme.bodySmall,
145+ colorCodeTextStyle: Theme .of (context).textTheme.bodySmall,
146+ pickersEnabled: const < ColorPickerType , bool > {
147+ ColorPickerType .both: true ,
148+ ColorPickerType .primary: false ,
149+ ColorPickerType .accent: false ,
150+ ColorPickerType .bw: false ,
151+ ColorPickerType .custom: false ,
152+ ColorPickerType .customSecondary: false ,
153+ ColorPickerType .wheel: false ,
154+ },
155+ showEditIconButton: true ,
156+ // customColorSwatchesAndNames: colorsNameMap,
147157 ),
148- ) ,
149- sizedBoxW4H4,
150- FilledButton (
151- onPressed : _advancedTabColor != Colors .transparent
152- ? () => Navigator . of (context). pop ( PickColorResult . picked (_advancedTabColor))
153- : null ,
154- child : Text (context.t.general.ok ),
155- ) ,
156- ] ,
158+ sizedBoxW4H4 ,
159+ FilledButton (
160+ onPressed : _advancedTabColor != Colors .transparent
161+ ? () => Navigator . of (context). pop ( PickColorResult . picked (_advancedTabColor))
162+ : null ,
163+ child : Text (context.t.general.ok) ,
164+ ),
165+ ] ,
166+ ) ,
157167 );
158168 }
159169
160170 Widget _buildCustomTab (BuildContext context) {
161171 final tr = context.t.colorPickerDialog.tabs.custom;
162172
163173 return Column (
174+ mainAxisSize: .min,
164175 children: [
165- Expanded (
166- child: SingleChildScrollView (
167- child: Column (
168- children: [
169- sizedBoxW8H8,
170- Row (
171- children: [
172- Expanded (
173- child: TextField (
174- controller: _customColorValueController,
175- decoration: InputDecoration (errorText: _customTabErrorText, labelText: tr.colorValue),
176- onChanged: _updateCustomColorPreview,
177- ),
178- ),
179- sizedBoxW12H12,
180- Container (
181- width: 40 ,
182- height: 40 ,
183- decoration: BoxDecoration (
184- borderRadius: const BorderRadius .all (Radius .circular (15 )),
185- color: _customTabColor,
186- ),
176+ sizedBoxW8H8,
177+ Row (
178+ children: [
179+ Expanded (
180+ child: TextField (
181+ controller: _customColorValueController,
182+ decoration: InputDecoration (errorText: _customTabErrorText, labelText: tr.colorValue),
183+ onChanged: _updateCustomColorPreview,
184+ ),
185+ ),
186+ sizedBoxW12H12,
187+ Container (
188+ width: 40 ,
189+ height: 40 ,
190+ decoration: BoxDecoration (
191+ borderRadius: const BorderRadius .all (Radius .circular (15 )),
192+ color: _customTabColor,
193+ ),
194+ ),
195+ ],
196+ ),
197+ sizedBoxW4H4,
198+ Tips (tr.formatTip, enablePadding: false ),
199+ sizedBoxW4H4,
200+ Text (tr.recentColor, style: Theme .of (context).textTheme.titleSmall),
201+ sizedBoxW4H4,
202+ Wrap (
203+ spacing: 4 ,
204+ children: _recentCustomColors
205+ .map (
206+ (e) => GestureDetector (
207+ onTap: () => setState (() {
208+ final value = e.hex.toLowerCase ();
209+ _updateCustomColorPreview (value);
210+ _customColorValueController.text = value;
211+ }),
212+ child: Container (
213+ width: 40 ,
214+ height: 40 ,
215+ decoration: BoxDecoration (
216+ borderRadius: const BorderRadius .all (Radius .circular (15 )),
217+ color: e,
187218 ),
188- ],
189- ),
190- sizedBoxW4H4,
191- Tips (tr.formatTip, enablePadding: false ),
192- sizedBoxW4H4,
193- Text (tr.recentColor, style: Theme .of (context).textTheme.titleSmall),
194- sizedBoxW4H4,
195- Wrap (
196- spacing: 4 ,
197- children: _recentCustomColors
198- .map (
199- (e) => GestureDetector (
200- onTap: () => setState (() {
201- final value = e.hex.toLowerCase ();
202- _updateCustomColorPreview (value);
203- _customColorValueController.text = value;
204- }),
205- child: Container (
206- width: 40 ,
207- height: 40 ,
208- decoration: BoxDecoration (
209- borderRadius: const BorderRadius .all (Radius .circular (15 )),
210- color: e,
211- ),
212- ),
213- ),
214- )
215- .toList (),
219+ ),
216220 ),
217- ],
218- ),
219- ),
221+ )
222+ .toList (),
220223 ),
221224 sizedBoxW4H4,
222225 FilledButton (
@@ -268,7 +271,7 @@ class _ColorBottomSheetState extends State<_ColorBottomSheet> with SingleTickerP
268271 @override
269272 void initState () {
270273 super .initState ();
271- _tabController = TabController (length: 3 , vsync: this );
274+ _tabController = TabController (length: 3 , vsync: this ).. addListener (onCurrentIndexChanged) ;
272275 _customColorValueController = TextEditingController ();
273276 if (widget.initialColor != null ) {
274277 WidgetsBinding .instance.addPostFrameCallback ((_) {
@@ -287,7 +290,9 @@ class _ColorBottomSheetState extends State<_ColorBottomSheet> with SingleTickerP
287290
288291 @override
289292 void dispose () {
290- _tabController.dispose ();
293+ _tabController
294+ ..removeListener (onCurrentIndexChanged)
295+ ..dispose ();
291296 _customColorValueController.dispose ();
292297 super .dispose ();
293298 }
@@ -296,38 +301,38 @@ class _ColorBottomSheetState extends State<_ColorBottomSheet> with SingleTickerP
296301 Widget build (BuildContext context) {
297302 final tr = context.t.colorPickerDialog;
298303
299- return ConstrainedBox (
300- constraints: const BoxConstraints (maxHeight: 450 ),
301- child: Column (
302- mainAxisSize: MainAxisSize .min,
303- children: [
304- TabBar (
305- controller: _tabController,
306- tabs: [
307- Tab (text: tr.tabs.normal.title),
308- Tab (text: tr.tabs.advanced.title),
309- Tab (text: tr.tabs.custom.title),
310- ],
311- ),
312- sizedBoxW4H4,
313- Expanded (
314- child: Padding (
315- padding: edgeInsetsL12R12,
316- child: TabBarView (
317- controller: _tabController,
318- children: [_buildNormalTab (), _buildAdvancedTab (), _buildCustomTab (context)],
319- ),
304+ return SingleChildScrollView (
305+ child: Padding (
306+ padding: edgeInsetsL12R12,
307+ child: Column (
308+ mainAxisSize: MainAxisSize .min,
309+ spacing: 4 ,
310+ children: [
311+ TabBar (
312+ controller: _tabController,
313+ tabs: [
314+ Tab (text: tr.tabs.normal.title),
315+ Tab (text: tr.tabs.advanced.title),
316+ Tab (text: tr.tabs.custom.title),
317+ ],
320318 ),
321- ),
322- sizedBoxW4H4 ,
323- Align (
324- alignment : Alignment .centerRight ,
325- child : TextButton (
326- onPressed : () => Navigator . of (context). pop ( PickColorResult . clearColor () ),
327- child : Text (context.t.general.reset) ,
319+ IndexedStack (
320+ index : currentIndex ,
321+ children : [
322+ _buildNormalTab () ,
323+ _buildAdvancedTab (),
324+ _buildCustomTab (context),
325+ ] ,
328326 ),
329- ),
330- ],
327+ Align (
328+ alignment: Alignment .centerRight,
329+ child: TextButton (
330+ onPressed: () => Navigator .of (context).pop (PickColorResult .clearColor ()),
331+ child: Text (context.t.general.reset),
332+ ),
333+ ),
334+ ],
335+ ),
331336 ),
332337 );
333338 }
0 commit comments