From 700961d56b1112780864b37aac586e4eaab1f2fa Mon Sep 17 00:00:00 2001 From: Mohamed Abdelbasit Date: Sun, 13 Jul 2025 18:25:27 +0300 Subject: [PATCH] 1- fix deprecated code 2- fix issue of color picker that was showing horizontal and vertical lines with the picker circle which was a bug and was an issue in ui 3- update example to use the latest version of flutter --- example/ios/Flutter/AppFrameworkInfo.plist | 2 +- example/ios/Runner.xcodeproj/project.pbxproj | 13 +- .../xcshareddata/xcschemes/Runner.xcscheme | 5 +- example/ios/Runner/AppDelegate.swift | 2 +- example/ios/Runner/Info.plist | 4 + example/lib/pickers/block_picker.dart | 87 ++-- example/lib/pickers/hsv_picker.dart | 149 +++++-- example/lib/pickers/material_picker.dart | 26 +- example/pubspec.lock | 20 +- lib/src/block_picker.dart | 44 +- lib/src/colorpicker.dart | 302 +++++++++----- lib/src/material_picker.dart | 234 +++++++---- lib/src/palette.dart | 388 ++++++++++++------ lib/src/utils.dart | 23 +- pubspec.lock | 80 ++-- 15 files changed, 912 insertions(+), 467 deletions(-) diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 8d4492f..7c56964 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 12.0 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 6edd238..2d5f6c6 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -127,7 +127,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -171,10 +171,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -185,6 +187,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -272,7 +275,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -349,7 +352,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -398,7 +401,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..fc5ae03 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -45,11 +46,13 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4..b636303 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index e5a8616..fb14919 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -41,5 +41,9 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/pickers/block_picker.dart b/example/lib/pickers/block_picker.dart index 062b64c..010d6a2 100644 --- a/example/lib/pickers/block_picker.dart +++ b/example/lib/pickers/block_picker.dart @@ -41,7 +41,8 @@ class BlockColorPickerExample extends StatefulWidget { final List colorHistory; @override - State createState() => _BlockColorPickerExampleState(); + State createState() => + _BlockColorPickerExampleState(); } class _BlockColorPickerExampleState extends State { @@ -51,14 +52,17 @@ class _BlockColorPickerExampleState extends State { double _blurRadius = 5; double _iconSize = 24; - Widget pickerLayoutBuilder(BuildContext context, List colors, PickerItem child) { + Widget pickerLayoutBuilder( + BuildContext context, List colors, PickerItem child) { Orientation orientation = MediaQuery.of(context).orientation; return SizedBox( width: 300, height: orientation == Orientation.portrait ? 360 : 240, child: GridView.count( - crossAxisCount: orientation == Orientation.portrait ? _portraitCrossAxisCount : _landscapeCrossAxisCount, + crossAxisCount: orientation == Orientation.portrait + ? _portraitCrossAxisCount + : _landscapeCrossAxisCount, crossAxisSpacing: 5, mainAxisSpacing: 5, children: [for (Color color in colors) child(color)], @@ -66,13 +70,19 @@ class _BlockColorPickerExampleState extends State { ); } - Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() changeColor) { + Widget pickerItemBuilder( + Color color, bool isCurrentColor, void Function() changeColor) { return Container( margin: const EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(_borderRadius), color: color, - boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: const Offset(1, 2), blurRadius: _blurRadius)], + boxShadow: [ + BoxShadow( + color: color.withValues(alpha: 0.8), + offset: const Offset(1, 2), + blurRadius: _blurRadius) + ], ), child: Material( color: Colors.transparent, @@ -131,10 +141,13 @@ Widget pickerLayoutBuilder(BuildContext context, List colors, PickerItem }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -150,7 +163,8 @@ Widget pickerLayoutBuilder(BuildContext context, List colors, PickerItem max: 10, divisions: 9, label: _portraitCrossAxisCount.toString(), - onChanged: (double value) => setState(() => _portraitCrossAxisCount = value.round()), + onChanged: (double value) => + setState(() => _portraitCrossAxisCount = value.round()), ), ), ), @@ -165,7 +179,8 @@ Widget pickerLayoutBuilder(BuildContext context, List colors, PickerItem max: 10, divisions: 9, label: _landscapeCrossAxisCount.toString(), - onChanged: (double value) => setState(() => _landscapeCrossAxisCount = value.round()), + onChanged: (double value) => + setState(() => _landscapeCrossAxisCount = value.round()), ), ), ), @@ -189,7 +204,7 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang decoration: BoxDecoration( borderRadius: BorderRadius.circular($_borderRadius), color: color, - boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: const Offset(1, 2), blurRadius: $_blurRadius)], + boxShadow: [BoxShadow(color: color.withValues(alpha:0.8), offset: const Offset(1, 2), blurRadius: $_blurRadius)], ), child: Material( color: Colors.transparent, @@ -216,10 +231,13 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -235,7 +253,8 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang max: 30, divisions: 30, label: _borderRadius.toString(), - onChanged: (double value) => setState(() => _borderRadius = value.round().toDouble()), + onChanged: (double value) => + setState(() => _borderRadius = value.round().toDouble()), ), ), ), @@ -250,7 +269,8 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang max: 5, divisions: 5, label: _blurRadius.toString(), - onChanged: (double value) => setState(() => _blurRadius = value.round().toDouble()), + onChanged: (double value) => + setState(() => _blurRadius = value.round().toDouble()), ), ), ), @@ -265,7 +285,8 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang max: 50, divisions: 49, label: _iconSize.toString(), - onChanged: (double value) => setState(() => _iconSize = value.round().toDouble()), + onChanged: (double value) => + setState(() => _iconSize = value.round().toDouble()), ), ), ), @@ -286,7 +307,9 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang child: BlockPicker( pickerColor: widget.pickerColor, onColorChanged: widget.onColorChanged, - availableColors: widget.colorHistory.isNotEmpty ? widget.colorHistory : colors, + availableColors: widget.colorHistory.isNotEmpty + ? widget.colorHistory + : colors, layoutBuilder: pickerLayoutBuilder, itemBuilder: pickerItemBuilder, ), @@ -297,11 +320,14 @@ Widget pickerItemBuilder(Color color, bool isCurrentColor, void Function() chang }, child: Text( 'Blocky Color Picker', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -331,10 +357,13 @@ BlockPicker( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -358,7 +387,9 @@ BlockPicker( child: MultipleChoiceBlockPicker( pickerColors: widget.pickerColors, onColorsChanged: widget.onColorsChanged, - availableColors: widget.colorHistory.isNotEmpty ? widget.colorHistory : colors, + availableColors: widget.colorHistory.isNotEmpty + ? widget.colorHistory + : colors, layoutBuilder: pickerLayoutBuilder, itemBuilder: pickerItemBuilder, ), @@ -369,11 +400,14 @@ BlockPicker( }, child: Text( 'Multiple selection Blocky Color Picker', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -403,10 +437,13 @@ MultipleChoiceBlockPicker( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), diff --git a/example/lib/pickers/hsv_picker.dart b/example/lib/pickers/hsv_picker.dart index de61c67..995de7d 100644 --- a/example/lib/pickers/hsv_picker.dart +++ b/example/lib/pickers/hsv_picker.dart @@ -35,7 +35,10 @@ class _HSVColorPickerExampleState extends State { PaletteType _paletteType = PaletteType.hsl; bool _enableAlpha = true; bool _displayThumbColor = true; - final List _labelTypes = [ColorLabelType.hsl, ColorLabelType.hsv]; + final List _labelTypes = [ + ColorLabelType.hsl, + ColorLabelType.hsv + ]; bool _displayHexInputBar = false; // Picker 2 @@ -50,8 +53,9 @@ class _HSVColorPickerExampleState extends State { bool _showIndicator = true; // Picker 4 - final textController = - TextEditingController(text: '#2F19DB'); // The initial value can be provided directly to the controller. + final textController = TextEditingController( + text: + '#2F19DB'); // The initial value can be provided directly to the controller. bool _enableAlpha4 = true; @override @@ -102,11 +106,14 @@ class _HSVColorPickerExampleState extends State { }, child: Text( 'Color Picker with Slider', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -144,10 +151,13 @@ ColorPicker( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -157,12 +167,14 @@ ColorPicker( title: const Text('Enable Alpha Slider'), subtitle: const Text('Display alpha slider & label text'), value: _enableAlpha, - onChanged: (bool value) => setState(() => _enableAlpha = !_enableAlpha), + onChanged: (bool value) => + setState(() => _enableAlpha = !_enableAlpha), ), SwitchListTile( title: const Text('Display Thumb Color in slider'), value: _displayThumbColor, - onChanged: (bool value) => setState(() => _displayThumbColor = !_displayThumbColor), + onChanged: (bool value) => + setState(() => _displayThumbColor = !_displayThumbColor), ), ListTile( title: const Text('Palette Type'), @@ -178,7 +190,8 @@ ColorPicker( value: type, child: SizedBox( width: 150, - child: Text(type.toString().split('.').last, textAlign: TextAlign.end), + child: Text(type.toString().split('.').last, + textAlign: TextAlign.end), ), ) ], @@ -186,16 +199,23 @@ ColorPicker( ), ), ExpansionTile( - title: Text(_labelTypes.isNotEmpty ? 'Display Label' : 'Disable Label'), + title: + Text(_labelTypes.isNotEmpty ? 'Display Label' : 'Disable Label'), subtitle: Text( - _labelTypes.isNotEmpty ? _labelTypes.map((e) => e.toString().split('.').last.toUpperCase()).toString() : '', + _labelTypes.isNotEmpty + ? _labelTypes + .map((e) => e.toString().split('.').last.toUpperCase()) + .toString() + : '', ), children: [ SwitchListTile( title: const Text(' Display HEX Label Text'), value: _labelTypes.contains(ColorLabelType.hex), onChanged: (bool value) => setState( - () => value ? _labelTypes.add(ColorLabelType.hex) : _labelTypes.remove(ColorLabelType.hex), + () => value + ? _labelTypes.add(ColorLabelType.hex) + : _labelTypes.remove(ColorLabelType.hex), ), dense: true, ), @@ -203,7 +223,9 @@ ColorPicker( title: const Text(' Display RGB Label Text'), value: _labelTypes.contains(ColorLabelType.rgb), onChanged: (bool value) => setState( - () => value ? _labelTypes.add(ColorLabelType.rgb) : _labelTypes.remove(ColorLabelType.rgb), + () => value + ? _labelTypes.add(ColorLabelType.rgb) + : _labelTypes.remove(ColorLabelType.rgb), ), dense: true, ), @@ -211,7 +233,9 @@ ColorPicker( title: const Text(' Display HSV Label Text'), value: _labelTypes.contains(ColorLabelType.hsv), onChanged: (bool value) => setState( - () => value ? _labelTypes.add(ColorLabelType.hsv) : _labelTypes.remove(ColorLabelType.hsv), + () => value + ? _labelTypes.add(ColorLabelType.hsv) + : _labelTypes.remove(ColorLabelType.hsv), ), dense: true, ), @@ -219,7 +243,9 @@ ColorPicker( title: const Text(' Display HSL Label Text'), value: _labelTypes.contains(ColorLabelType.hsl), onChanged: (bool value) => setState( - () => value ? _labelTypes.add(ColorLabelType.hsl) : _labelTypes.remove(ColorLabelType.hsl), + () => value + ? _labelTypes.add(ColorLabelType.hsl) + : _labelTypes.remove(ColorLabelType.hsl), ), dense: true, ), @@ -228,7 +254,8 @@ ColorPicker( SwitchListTile( title: const Text('Display Hex Input Bar'), value: _displayHexInputBar, - onChanged: (bool value) => setState(() => _displayHexInputBar = !_displayHexInputBar), + onChanged: (bool value) => + setState(() => _displayHexInputBar = !_displayHexInputBar), ), const Divider(), const SizedBox(height: 5), @@ -245,12 +272,14 @@ ColorPicker( titlePadding: const EdgeInsets.all(0), contentPadding: const EdgeInsets.all(0), shape: RoundedRectangleBorder( - borderRadius: MediaQuery.of(context).orientation == Orientation.portrait + borderRadius: MediaQuery.of(context).orientation == + Orientation.portrait ? const BorderRadius.vertical( top: Radius.circular(500), bottom: Radius.circular(100), ) - : const BorderRadius.horizontal(right: Radius.circular(500)), + : const BorderRadius.horizontal( + right: Radius.circular(500)), ), content: SingleChildScrollView( child: HueRingPicker( @@ -266,11 +295,14 @@ ColorPicker( }, child: Text( 'Hue Ring Picker with Hex Input', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -297,10 +329,13 @@ HueRingPicker( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -309,12 +344,14 @@ HueRingPicker( SwitchListTile( title: const Text('Enable Alpha Slider'), value: _enableAlpha2, - onChanged: (bool value) => setState(() => _enableAlpha2 = !_enableAlpha2), + onChanged: (bool value) => + setState(() => _enableAlpha2 = !_enableAlpha2), ), SwitchListTile( title: const Text('Display Thumb Color in Slider'), value: _displayThumbColor2, - onChanged: (bool value) => setState(() => _displayThumbColor2 = !_displayThumbColor2), + onChanged: (bool value) => + setState(() => _displayThumbColor2 = !_displayThumbColor2), ), const Divider(), const SizedBox(height: 5), @@ -330,7 +367,8 @@ HueRingPicker( return AlertDialog( titlePadding: const EdgeInsets.all(0), contentPadding: const EdgeInsets.all(0), - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(25))), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(25))), content: SingleChildScrollView( child: SlidePicker( pickerColor: widget.pickerColor, @@ -340,7 +378,8 @@ HueRingPicker( displayThumbColor: _displayThumbColor3, showParams: _showParams, showIndicator: _showIndicator, - indicatorBorderRadius: const BorderRadius.vertical(top: Radius.circular(25)), + indicatorBorderRadius: const BorderRadius.vertical( + top: Radius.circular(25)), ), ), ); @@ -349,11 +388,14 @@ HueRingPicker( }, child: Text( 'Slider-only Color Picker', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -384,10 +426,13 @@ SlidePicker( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -407,7 +452,8 @@ SlidePicker( value: type, child: SizedBox( width: 50, - child: Text(type.toString().split('.').last, textAlign: TextAlign.end), + child: Text(type.toString().split('.').last, + textAlign: TextAlign.end), ), ) ], @@ -417,12 +463,14 @@ SlidePicker( SwitchListTile( title: const Text('Enable Alpha Slider'), value: _enableAlpha3, - onChanged: (bool value) => setState(() => _enableAlpha3 = !_enableAlpha3), + onChanged: (bool value) => + setState(() => _enableAlpha3 = !_enableAlpha3), ), SwitchListTile( title: const Text('Display Thumb Color in Slider'), value: _displayThumbColor3, - onChanged: (bool value) => setState(() => _displayThumbColor3 = !_displayThumbColor3), + onChanged: (bool value) => + setState(() => _displayThumbColor3 = !_displayThumbColor3), ), SwitchListTile( title: const Text('Show Parameters next to Slider'), @@ -432,7 +480,8 @@ SlidePicker( SwitchListTile( title: const Text('Show Color Indicator'), value: _showIndicator, - onChanged: (bool value) => setState(() => _showIndicator = !_showIndicator), + onChanged: (bool value) => + setState(() => _showIndicator = !_showIndicator), ), const Divider(), const SizedBox(height: 15), @@ -456,7 +505,8 @@ SlidePicker( onColorChanged: widget.onColorChanged, colorPickerWidth: 300, pickerAreaHeightPercent: 0.7, - enableAlpha: _enableAlpha4, // hexInputController will respect it too. + enableAlpha: + _enableAlpha4, // hexInputController will respect it too. displayThumbColor: true, paletteType: PaletteType.hsvWithHue, labelTypes: const [], @@ -484,10 +534,13 @@ SlidePicker( child: CupertinoTextField( controller: textController, // Everything below is purely optional. - prefix: const Padding(padding: EdgeInsets.only(left: 8), child: Icon(Icons.tag)), + prefix: const Padding( + padding: EdgeInsets.only(left: 8), + child: Icon(Icons.tag)), suffix: IconButton( icon: const Icon(Icons.content_paste_rounded), - onPressed: () => copyToClipboard(textController.text), + onPressed: () => + copyToClipboard(textController.text), ), autofocus: true, maxLength: 9, @@ -495,7 +548,8 @@ SlidePicker( // Any custom input formatter can be passed // here or use any Form validator you want. UpperCaseTextFormatter(), - FilteringTextInputFormatter.allow(RegExp(kValidHexPattern)), + FilteringTextInputFormatter.allow( + RegExp(kValidHexPattern)), ], ), ) @@ -507,11 +561,14 @@ SlidePicker( }, child: Text( ' HSV Color Picker\n(Your own text field)', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -569,10 +626,13 @@ Column( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -581,7 +641,8 @@ Column( SwitchListTile( title: const Text('Enable Alpha Slider'), value: _enableAlpha4, - onChanged: (bool value) => setState(() => _enableAlpha4 = !_enableAlpha4), + onChanged: (bool value) => + setState(() => _enableAlpha4 = !_enableAlpha4), ), const SizedBox(height: 80), ], diff --git a/example/lib/pickers/material_picker.dart b/example/lib/pickers/material_picker.dart index 3fd133d..d631047 100644 --- a/example/lib/pickers/material_picker.dart +++ b/example/lib/pickers/material_picker.dart @@ -12,10 +12,12 @@ class MaterialColorPickerExample extends StatefulWidget { final ValueChanged onColorChanged; @override - State createState() => _MaterialColorPickerExampleState(); + State createState() => + _MaterialColorPickerExampleState(); } -class _MaterialColorPickerExampleState extends State { +class _MaterialColorPickerExampleState + extends State { bool _enableLabel = true; bool _portraitOnly = false; @@ -50,11 +52,14 @@ class _MaterialColorPickerExampleState extends State }, child: Text( 'Kiss Me with Your Finger', - style: TextStyle(color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + style: TextStyle( + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), ), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -83,10 +88,13 @@ MaterialPicker( }, ); }, - child: Icon(Icons.code, color: useWhiteForeground(widget.pickerColor) ? Colors.white : Colors.black), + child: Icon(Icons.code, + color: useWhiteForeground(widget.pickerColor) + ? Colors.white + : Colors.black), style: ElevatedButton.styleFrom( backgroundColor: widget.pickerColor, - shadowColor: widget.pickerColor.withOpacity(1), + shadowColor: widget.pickerColor.withValues(alpha: 1), elevation: 10, ), ), @@ -95,12 +103,14 @@ MaterialPicker( SwitchListTile( title: const Text('Enable Label in Portrait Mode'), value: _enableLabel, - onChanged: (bool value) => setState(() => _enableLabel = !_enableLabel), + onChanged: (bool value) => + setState(() => _enableLabel = !_enableLabel), ), SwitchListTile( title: const Text('Apply Portrait layout to Landscape Mode'), value: _portraitOnly, - onChanged: (bool value) => setState(() => _portraitOnly = !_portraitOnly), + onChanged: (bool value) => + setState(() => _portraitOnly = !_portraitOnly), ), ], ); diff --git a/example/pubspec.lock b/example/pubspec.lock index 36973bb..b612d53 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" flutter: dependency: "direct main" description: flutter @@ -49,23 +49,23 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.16.0" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" vector_math: dependency: transitive description: @@ -75,5 +75,5 @@ packages: source: hosted version: "2.1.4" sdks: - dart: ">=3.3.0-0 <4.0.0" + dart: ">=3.7.0-0 <4.0.0" flutter: ">=2.0.0" diff --git a/lib/src/block_picker.dart b/lib/src/block_picker.dart index dbf780c..90f9111 100644 --- a/lib/src/block_picker.dart +++ b/lib/src/block_picker.dart @@ -3,16 +3,19 @@ library block_colorpicker; import 'package:flutter/material.dart'; + import 'utils.dart'; /// Child widget for layout builder. typedef PickerItem = Widget Function(Color color); /// Customize the layout. -typedef PickerLayoutBuilder = Widget Function(BuildContext context, List colors, PickerItem child); +typedef PickerLayoutBuilder = Widget Function( + BuildContext context, List colors, PickerItem child); /// Customize the item shape. -typedef PickerItemBuilder = Widget Function(Color color, bool isCurrentColor, void Function() changeColor); +typedef PickerItemBuilder = Widget Function( + Color color, bool isCurrentColor, void Function() changeColor); // Provide a list of colors for block color picker. const List _defaultColors = [ @@ -39,7 +42,8 @@ const List _defaultColors = [ ]; // Provide a layout for [BlockPicker]. -Widget _defaultLayoutBuilder(BuildContext context, List colors, PickerItem child) { +Widget _defaultLayoutBuilder( + BuildContext context, List colors, PickerItem child) { Orientation orientation = MediaQuery.of(context).orientation; return SizedBox( @@ -55,13 +59,19 @@ Widget _defaultLayoutBuilder(BuildContext context, List colors, PickerIte } // Provide a shape for [BlockPicker]. -Widget _defaultItemBuilder(Color color, bool isCurrentColor, void Function() changeColor) { +Widget _defaultItemBuilder( + Color color, bool isCurrentColor, void Function() changeColor) { return Container( margin: const EdgeInsets.all(7), decoration: BoxDecoration( shape: BoxShape.circle, color: color, - boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: const Offset(1, 2), blurRadius: 5)], + boxShadow: [ + BoxShadow( + color: color.withValues(alpha: 0.8), + offset: const Offset(1, 2), + blurRadius: 5) + ], ), child: Material( color: Colors.transparent, @@ -71,7 +81,8 @@ Widget _defaultItemBuilder(Color color, bool isCurrentColor, void Function() cha child: AnimatedOpacity( duration: const Duration(milliseconds: 210), opacity: isCurrentColor ? 1 : 0, - child: Icon(Icons.done, color: useWhiteForeground(color) ? Colors.white : Colors.black), + child: Icon(Icons.done, + color: useWhiteForeground(color) ? Colors.white : Colors.black), ), ), ), @@ -122,9 +133,12 @@ class _BlockPickerState extends State { widget.availableColors, (Color color) => widget.itemBuilder( color, - (_currentColor != null && (widget.useInShowDialog ? true : widget.pickerColor != null)) - ? (_currentColor?.value == color.value) && - (widget.useInShowDialog ? true : widget.pickerColor?.value == color.value) + (_currentColor != null && + (widget.useInShowDialog ? true : widget.pickerColor != null)) + ? (_currentColor?.toARGB32() == color.toARGB32()) && + (widget.useInShowDialog + ? true + : widget.pickerColor?.toARGB32() == color.toARGB32()) : false, () => changeColor(color), ), @@ -167,7 +181,9 @@ class _MultipleChoiceBlockPickerState extends State { void toggleColor(Color color) { setState(() { if (_currentColors != null) { - _currentColors!.contains(color) ? _currentColors!.remove(color) : _currentColors!.add(color); + _currentColors!.contains(color) + ? _currentColors!.remove(color) + : _currentColors!.add(color); } }); widget.onColorsChanged(_currentColors ?? []); @@ -180,8 +196,12 @@ class _MultipleChoiceBlockPickerState extends State { widget.availableColors, (Color color) => widget.itemBuilder( color, - (_currentColors != null && (widget.useInShowDialog ? true : widget.pickerColors != null)) - ? _currentColors!.contains(color) && (widget.useInShowDialog ? true : widget.pickerColors!.contains(color)) + (_currentColors != null && + (widget.useInShowDialog ? true : widget.pickerColors != null)) + ? _currentColors!.contains(color) && + (widget.useInShowDialog + ? true + : widget.pickerColors!.contains(color)) : false, () => toggleColor(color), ), diff --git a/lib/src/colorpicker.dart b/lib/src/colorpicker.dart index 67ca33a..7dfc587 100644 --- a/lib/src/colorpicker.dart +++ b/lib/src/colorpicker.dart @@ -5,6 +5,7 @@ library hsv_picker; import 'package:flutter/material.dart'; + import 'palette.dart'; import 'utils.dart'; @@ -18,9 +19,16 @@ class ColorPicker extends StatefulWidget { this.onHsvColorChanged, this.paletteType = PaletteType.hsvWithHue, this.enableAlpha = true, - @Deprecated('Use empty list in [labelTypes] to disable label.') this.showLabel = true, - this.labelTypes = const [ColorLabelType.rgb, ColorLabelType.hsv, ColorLabelType.hsl], - @Deprecated('Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') this.labelTextStyle, + @Deprecated('Use empty list in [labelTypes] to disable label.') + this.showLabel = true, + this.labelTypes = const [ + ColorLabelType.rgb, + ColorLabelType.hsv, + ColorLabelType.hsl + ], + @Deprecated( + 'Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') + this.labelTextStyle, this.displayThumbColor = false, this.portraitOnly = false, this.colorPickerWidth = 300.0, @@ -166,8 +174,9 @@ class _ColorPickerState extends State { @override void initState() { - currentHsvColor = - (widget.pickerHsvColor != null) ? widget.pickerHsvColor as HSVColor : HSVColor.fromColor(widget.pickerColor); + currentHsvColor = (widget.pickerHsvColor != null) + ? widget.pickerHsvColor as HSVColor + : HSVColor.fromColor(widget.pickerColor); // If there's no initial text in `hexInputController`, if (widget.hexInputController?.text.isEmpty == true) { // set it to the current's color HEX value. @@ -187,8 +196,9 @@ class _ColorPickerState extends State { @override void didUpdateWidget(ColorPicker oldWidget) { super.didUpdateWidget(oldWidget); - currentHsvColor = - (widget.pickerHsvColor != null) ? widget.pickerHsvColor as HSVColor : HSVColor.fromColor(widget.pickerColor); + currentHsvColor = (widget.pickerHsvColor != null) + ? widget.pickerHsvColor as HSVColor + : HSVColor.fromColor(widget.pickerColor); } void colorPickerTextInputListener() { @@ -197,14 +207,17 @@ class _ColorPickerState extends State { if (widget.hexInputController == null) return; // If a user is inserting/typing any text — try to get the color value from it, // and interpret its transparency, dependent on the widget's settings. - final Color? color = colorFromHex(widget.hexInputController!.text, enableAlpha: widget.enableAlpha); + final Color? color = colorFromHex(widget.hexInputController!.text, + enableAlpha: widget.enableAlpha); // If it's the valid color: if (color != null) { // set it as the current color and setState(() => currentHsvColor = HSVColor.fromColor(color)); // notify with a callback. widget.onColorChanged(color); - if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); + if (widget.onHsvColorChanged != null) { + widget.onHsvColorChanged!(currentHsvColor); + } } } @@ -220,10 +233,13 @@ class _ColorPickerState extends State { currentHsvColor, (HSVColor color) { // Update text in `hexInputController` if provided. - widget.hexInputController?.text = colorToHex(color.toColor(), enableAlpha: widget.enableAlpha); + widget.hexInputController?.text = + colorToHex(color.toColor(), enableAlpha: widget.enableAlpha); setState(() => currentHsvColor = color); widget.onColorChanged(currentHsvColor.toColor()); - if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); + if (widget.onHsvColorChanged != null) { + widget.onHsvColorChanged!(currentHsvColor); + } }, displayThumbColor: widget.displayThumbColor, ); @@ -231,18 +247,23 @@ class _ColorPickerState extends State { void onColorChanging(HSVColor color) { // Update text in `hexInputController` if provided. - widget.hexInputController?.text = colorToHex(color.toColor(), enableAlpha: widget.enableAlpha); + widget.hexInputController?.text = + colorToHex(color.toColor(), enableAlpha: widget.enableAlpha); setState(() => currentHsvColor = color); widget.onColorChanged(currentHsvColor.toColor()); - if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); + if (widget.onHsvColorChanged != null) { + widget.onHsvColorChanged!(currentHsvColor); + } } Widget colorPicker() { return ClipRRect( borderRadius: widget.pickerAreaBorderRadius, child: Padding( - padding: EdgeInsets.all(widget.paletteType == PaletteType.hueWheel ? 10 : 0), - child: ColorPickerArea(currentHsvColor, onColorChanging, widget.paletteType), + padding: + EdgeInsets.all(widget.paletteType == PaletteType.hueWheel ? 10 : 0), + child: ColorPickerArea( + currentHsvColor, onColorChanging, widget.paletteType), ), ); } @@ -276,7 +297,8 @@ class _ColorPickerState extends State { @override Widget build(BuildContext context) { - if (MediaQuery.of(context).orientation == Orientation.portrait || widget.portraitOnly) { + if (MediaQuery.of(context).orientation == Orientation.portrait || + widget.portraitOnly) { return Column( children: [ SizedBox( @@ -291,7 +313,8 @@ class _ColorPickerState extends State { children: [ GestureDetector( onTap: () => setState(() { - if (widget.onHistoryChanged != null && !colorHistory.contains(currentHsvColor.toColor())) { + if (widget.onHistoryChanged != null && + !colorHistory.contains(currentHsvColor.toColor())) { colorHistory.add(currentHsvColor.toColor()); widget.onHistoryChanged!(colorHistory); } @@ -301,7 +324,10 @@ class _ColorPickerState extends State { Expanded( child: Column( children: [ - SizedBox(height: 40.0, width: widget.colorPickerWidth - 75.0, child: sliderByPaletteType()), + SizedBox( + height: 40.0, + width: widget.colorPickerWidth - 75.0, + child: sliderByPaletteType()), if (widget.enableAlpha) SizedBox( height: 40.0, @@ -318,7 +344,8 @@ class _ColorPickerState extends State { SizedBox( width: widget.colorPickerWidth, height: 50, - child: ListView(scrollDirection: Axis.horizontal, children: [ + child: + ListView(scrollDirection: Axis.horizontal, children: [ for (Color color in colorHistory) Padding( key: Key(color.hashCode.toString()), @@ -326,7 +353,8 @@ class _ColorPickerState extends State { child: Center( child: GestureDetector( onTap: () => onColorChanging(HSVColor.fromColor(color)), - child: ColorIndicator(HSVColor.fromColor(color), width: 30, height: 30), + child: ColorIndicator(HSVColor.fromColor(color), + width: 30, height: 30), ), ), ), @@ -348,7 +376,9 @@ class _ColorPickerState extends State { (Color color) { setState(() => currentHsvColor = HSVColor.fromColor(color)); widget.onColorChanged(currentHsvColor.toColor()); - if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); + if (widget.onHsvColorChanged != null) { + widget.onHsvColorChanged!(currentHsvColor); + } }, enableAlpha: widget.enableAlpha, embeddedText: false, @@ -370,7 +400,8 @@ class _ColorPickerState extends State { const SizedBox(width: 20.0), GestureDetector( onTap: () => setState(() { - if (widget.onHistoryChanged != null && !colorHistory.contains(currentHsvColor.toColor())) { + if (widget.onHistoryChanged != null && + !colorHistory.contains(currentHsvColor.toColor())) { colorHistory.add(currentHsvColor.toColor()); widget.onHistoryChanged!(colorHistory); } @@ -379,9 +410,15 @@ class _ColorPickerState extends State { ), Column( children: [ - SizedBox(height: 40.0, width: 260.0, child: sliderByPaletteType()), + SizedBox( + height: 40.0, + width: 260.0, + child: sliderByPaletteType()), if (widget.enableAlpha) - SizedBox(height: 40.0, width: 260.0, child: colorPickerSlider(TrackType.alpha)), + SizedBox( + height: 40.0, + width: 260.0, + child: colorPickerSlider(TrackType.alpha)), ], ), const SizedBox(width: 10.0), @@ -391,26 +428,30 @@ class _ColorPickerState extends State { SizedBox( width: widget.colorPickerWidth, height: 50, - child: ListView(scrollDirection: Axis.horizontal, children: [ - for (Color color in colorHistory) - Padding( - key: Key(color.hashCode.toString()), - padding: const EdgeInsets.fromLTRB(15, 18, 0, 0), - child: Center( - child: GestureDetector( - onTap: () => onColorChanging(HSVColor.fromColor(color)), - onLongPress: () { - if (colorHistory.remove(color)) { - widget.onHistoryChanged!(colorHistory); - setState(() {}); - } - }, - child: ColorIndicator(HSVColor.fromColor(color), width: 30, height: 30), + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + for (Color color in colorHistory) + Padding( + key: Key(color.hashCode.toString()), + padding: const EdgeInsets.fromLTRB(15, 18, 0, 0), + child: Center( + child: GestureDetector( + onTap: () => + onColorChanging(HSVColor.fromColor(color)), + onLongPress: () { + if (colorHistory.remove(color)) { + widget.onHistoryChanged!(colorHistory); + setState(() {}); + } + }, + child: ColorIndicator(HSVColor.fromColor(color), + width: 30, height: 30), + ), + ), ), - ), - ), - const SizedBox(width: 15), - ]), + const SizedBox(width: 15), + ]), ), const SizedBox(height: 20.0), if (widget.showLabel && widget.labelTypes.isNotEmpty) @@ -428,7 +469,9 @@ class _ColorPickerState extends State { (Color color) { setState(() => currentHsvColor = HSVColor.fromColor(color)); widget.onColorChanged(currentHsvColor.toColor()); - if (widget.onHsvColorChanged != null) widget.onHsvColorChanged!(currentHsvColor); + if (widget.onHsvColorChanged != null) { + widget.onHsvColorChanged!(currentHsvColor); + } }, enableAlpha: widget.enableAlpha, embeddedText: false, @@ -452,11 +495,16 @@ class SlidePicker extends StatefulWidget { this.enableAlpha = true, this.sliderSize = const Size(260, 40), this.showSliderText = true, - @Deprecated('Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') this.sliderTextStyle, + @Deprecated( + 'Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') + this.sliderTextStyle, this.showParams = true, - @Deprecated('Use empty list in [labelTypes] to disable label.') this.showLabel = true, + @Deprecated('Use empty list in [labelTypes] to disable label.') + this.showLabel = true, this.labelTypes = const [], - @Deprecated('Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') this.labelTextStyle, + @Deprecated( + 'Use Theme.of(context).textTheme.bodyText1 & 2 to alter text style.') + this.labelTextStyle, this.showIndicator = true, this.indicatorSize = const Size(280, 50), this.indicatorAlignmentBegin = const Alignment(-1.0, -3.0), @@ -521,7 +569,8 @@ class _SlidePickerState extends State { clipBehavior: Clip.antiAliasWithSaveLayer, child: GestureDetector( onTap: () { - setState(() => currentHsvColor = HSVColor.fromColor(widget.pickerColor)); + setState( + () => currentHsvColor = HSVColor.fromColor(widget.pickerColor)); widget.onColorChanged(currentHsvColor.toColor()); }, child: Container( @@ -552,10 +601,10 @@ class _SlidePickerState extends State { if (widget.colorModel == ColorModel.rgb) { final Color color = currentHsvColor.toColor(); return [ - color.red.toString(), - color.green.toString(), - color.blue.toString(), - '${(color.opacity * 100).round()}', + ((color.r * 255.0).round() & 0xff).toString(), + ((color.g * 255.0).round() & 0xff).toString(), + ((color.b * 255.0).round() & 0xff).toString(), + '${((color.a * 255.0).round() & 0xff)}', ][pos]; } else if (widget.colorModel == ColorModel.hsv) { return [ @@ -582,9 +631,21 @@ class _SlidePickerState extends State { final double fontSize = widget.labelTextStyle?.fontSize ?? 14; final List trackTypes = [ - if (widget.colorModel == ColorModel.hsv) ...[TrackType.hue, TrackType.saturation, TrackType.value], - if (widget.colorModel == ColorModel.hsl) ...[TrackType.hue, TrackType.saturationForHSL, TrackType.lightness], - if (widget.colorModel == ColorModel.rgb) ...[TrackType.red, TrackType.green, TrackType.blue], + if (widget.colorModel == ColorModel.hsv) ...[ + TrackType.hue, + TrackType.saturation, + TrackType.value + ], + if (widget.colorModel == ColorModel.hsl) ...[ + TrackType.hue, + TrackType.saturationForHSL, + TrackType.lightness + ], + if (widget.colorModel == ColorModel.rgb) ...[ + TrackType.red, + TrackType.green, + TrackType.blue + ], if (widget.enableAlpha) ...[TrackType.alpha], ]; List sliders = [ @@ -599,7 +660,8 @@ class _SlidePickerState extends State { padding: const EdgeInsets.symmetric(horizontal: 10.0), child: Text( trackType.toString().split('.').last[0].toUpperCase(), - style: widget.sliderTextStyle ?? Theme.of(context).textTheme.bodyLarge, + style: widget.sliderTextStyle ?? + Theme.of(context).textTheme.bodyLarge, ), ), Expanded(child: colorPickerSlider(trackType)), @@ -608,7 +670,8 @@ class _SlidePickerState extends State { constraints: BoxConstraints(minWidth: fontSize * 2 + 5), child: Text( getColorParams(trackTypes.indexOf(trackType)), - style: widget.sliderTextStyle ?? Theme.of(context).textTheme.bodyMedium, + style: widget.sliderTextStyle ?? + Theme.of(context).textTheme.bodyMedium, textAlign: TextAlign.right, ), ), @@ -639,7 +702,7 @@ class _SlidePickerState extends State { ); } } - + /// The Color Picker with HUE Ring & HSV model. class HueRingPicker extends StatefulWidget { const HueRingPicker({ @@ -689,30 +752,34 @@ class _HueRingPickerState extends State { @override Widget build(BuildContext context) { - if (MediaQuery.of(context).orientation == Orientation.portrait || widget.portraitOnly) { + if (MediaQuery.of(context).orientation == Orientation.portrait || + widget.portraitOnly) { return Column( children: [ ClipRRect( borderRadius: widget.pickerAreaBorderRadius, child: Padding( padding: const EdgeInsets.all(15), - child: Stack(alignment: AlignmentDirectional.center, children: [ - SizedBox( - width: widget.colorPickerHeight, - height: widget.colorPickerHeight, - child: ColorPickerHueRing( - currentHsvColor, - onColorChanging, - displayThumbColor: widget.displayThumbColor, - strokeWidth: widget.hueRingStrokeWidth, - ), - ), - SizedBox( - width: widget.colorPickerHeight / 1.6, - height: widget.colorPickerHeight / 1.6, - child: ColorPickerArea(currentHsvColor, onColorChanging, PaletteType.hsv), - ) - ]), + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + SizedBox( + width: widget.colorPickerHeight, + height: widget.colorPickerHeight, + child: ColorPickerHueRing( + currentHsvColor, + onColorChanging, + displayThumbColor: widget.displayThumbColor, + strokeWidth: widget.hueRingStrokeWidth, + ), + ), + SizedBox( + width: widget.colorPickerHeight / 1.6, + height: widget.colorPickerHeight / 1.6, + child: ColorPickerArea( + currentHsvColor, onColorChanging, PaletteType.hsv), + ) + ]), ), ), if (widget.enableAlpha) @@ -739,7 +806,8 @@ class _HueRingPickerState extends State { child: ColorPickerInput( currentHsvColor.toColor(), (Color color) { - setState(() => currentHsvColor = HSVColor.fromColor(color)); + setState( + () => currentHsvColor = HSVColor.fromColor(color)); widget.onColorChanged(currentHsvColor.toColor()); }, enableAlpha: widget.enableAlpha, @@ -761,7 +829,8 @@ class _HueRingPickerState extends State { height: widget.colorPickerHeight, child: ClipRRect( borderRadius: widget.pickerAreaBorderRadius, - child: ColorPickerArea(currentHsvColor, onColorChanging, PaletteType.hsv), + child: ColorPickerArea( + currentHsvColor, onColorChanging, PaletteType.hsv), ), ), ), @@ -769,42 +838,51 @@ class _HueRingPickerState extends State { borderRadius: widget.pickerAreaBorderRadius, child: Padding( padding: const EdgeInsets.all(15), - child: Stack(alignment: AlignmentDirectional.topCenter, children: [ - SizedBox( - width: widget.colorPickerHeight - widget.hueRingStrokeWidth * 2, - height: widget.colorPickerHeight - widget.hueRingStrokeWidth * 2, - child: ColorPickerHueRing(currentHsvColor, onColorChanging, strokeWidth: widget.hueRingStrokeWidth), - ), - Column( - children: [ - SizedBox(height: widget.colorPickerHeight / 8.5), - ColorIndicator(currentHsvColor), - const SizedBox(height: 10), - ColorPickerInput( - currentHsvColor.toColor(), - (Color color) { - setState(() => currentHsvColor = HSVColor.fromColor(color)); - widget.onColorChanged(currentHsvColor.toColor()); - }, - enableAlpha: widget.enableAlpha, - embeddedText: true, - disable: true, + child: Stack( + alignment: AlignmentDirectional.topCenter, + children: [ + SizedBox( + width: widget.colorPickerHeight - + widget.hueRingStrokeWidth * 2, + height: widget.colorPickerHeight - + widget.hueRingStrokeWidth * 2, + child: ColorPickerHueRing( + currentHsvColor, onColorChanging, + strokeWidth: widget.hueRingStrokeWidth), ), - if (widget.enableAlpha) const SizedBox(height: 5), - if (widget.enableAlpha) - SizedBox( - height: 40.0, - width: (widget.colorPickerHeight - widget.hueRingStrokeWidth * 2) / 2, - child: ColorPickerSlider( - TrackType.alpha, - currentHsvColor, - onColorChanging, - displayThumbColor: true, + Column( + children: [ + SizedBox(height: widget.colorPickerHeight / 8.5), + ColorIndicator(currentHsvColor), + const SizedBox(height: 10), + ColorPickerInput( + currentHsvColor.toColor(), + (Color color) { + setState(() => + currentHsvColor = HSVColor.fromColor(color)); + widget.onColorChanged(currentHsvColor.toColor()); + }, + enableAlpha: widget.enableAlpha, + embeddedText: true, + disable: true, ), - ), - ], - ), - ]), + if (widget.enableAlpha) const SizedBox(height: 5), + if (widget.enableAlpha) + SizedBox( + height: 40.0, + width: (widget.colorPickerHeight - + widget.hueRingStrokeWidth * 2) / + 2, + child: ColorPickerSlider( + TrackType.alpha, + currentHsvColor, + onColorChanging, + displayThumbColor: true, + ), + ), + ], + ), + ]), ), ), ], diff --git a/lib/src/material_picker.dart b/lib/src/material_picker.dart index cc7d12e..64e995f 100644 --- a/lib/src/material_picker.dart +++ b/lib/src/material_picker.dart @@ -4,6 +4,7 @@ library material_colorpicker; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; + import 'utils.dart'; // The Color Picker which contains Material Design Color Palette. @@ -59,16 +60,29 @@ class _MaterialPickerState extends State { for (Color colorType in colors) { if (colorType == Colors.grey) { - result.addAll([50, 100, 200, 300, 350, 400, 500, 600, 700, 800, 850, 900] - .map((int shade) => {Colors.grey[shade]!: shade.toString()}) - .toList()); + result.addAll([ + 50, + 100, + 200, + 300, + 350, + 400, + 500, + 600, + 700, + 800, + 850, + 900 + ].map((int shade) => {Colors.grey[shade]!: shade.toString()}).toList()); } else if (colorType == Colors.black || colorType == Colors.white) { result.addAll([ {Colors.black: ''}, {Colors.white: ''} ]); } else if (colorType is MaterialAccentColor) { - result.addAll([100, 200, 400, 700].map((int shade) => {colorType[shade]!: 'A$shade'}).toList()); + result.addAll([100, 200, 400, 700] + .map((int shade) => {colorType[shade]!: 'A$shade'}) + .toList()); } else if (colorType is MaterialColor) { result.addAll([50, 100, 200, 300, 400, 500, 600, 700, 800, 900] .map((int shade) => {colorType[shade]!: shade.toString()}) @@ -85,7 +99,7 @@ class _MaterialPickerState extends State { void initState() { for (List _colors in _colorTypes) { _shadingTypes(_colors).forEach((Map color) { - if (widget.pickerColor.value == color.keys.first.value) { + if (widget.pickerColor.toARGB32() == color.keys.first.toARGB32()) { return setState(() { _currentColorType = _colors; _currentShading = color.keys.first; @@ -98,25 +112,50 @@ class _MaterialPickerState extends State { @override Widget build(BuildContext context) { - bool _isPortrait = MediaQuery.of(context).orientation == Orientation.portrait || widget.portraitOnly; + bool _isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait || + widget.portraitOnly; Widget _colorList() { return Container( clipBehavior: Clip.hardEdge, decoration: const BoxDecoration(), child: Container( - margin: _isPortrait ? const EdgeInsets.only(right: 10) : const EdgeInsets.only(bottom: 10), + margin: _isPortrait + ? const EdgeInsets.only(right: 10) + : const EdgeInsets.only(bottom: 10), width: _isPortrait ? 60 : null, height: _isPortrait ? null : 60, decoration: BoxDecoration( color: Theme.of(context).cardColor, - boxShadow: [BoxShadow(color: (Theme.of(context).brightness == Brightness.light) ? (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38 : Colors.black38, blurRadius: 10)], + boxShadow: [ + BoxShadow( + color: (Theme.of(context).brightness == Brightness.light) + ? (Theme.of(context).brightness == Brightness.light) + ? Colors.grey[300]! + : Colors.black38 + : Colors.black38, + blurRadius: 10) + ], border: _isPortrait - ? Border(right: BorderSide(color: (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38, width: 1)) - : Border(top: BorderSide(color: (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38, width: 1)), + ? Border( + right: BorderSide( + color: + (Theme.of(context).brightness == Brightness.light) + ? Colors.grey[300]! + : Colors.black38, + width: 1)) + : Border( + top: BorderSide( + color: + (Theme.of(context).brightness == Brightness.light) + ? Colors.grey[300]! + : Colors.black38, + width: 1)), ), child: ScrollConfiguration( - behavior: ScrollConfiguration.of(context).copyWith(dragDevices: PointerDeviceKind.values.toSet()), + behavior: ScrollConfiguration.of(context) + .copyWith(dragDevices: PointerDeviceKind.values.toSet()), child: ListView( scrollDirection: _isPortrait ? Axis.vertical : Axis.horizontal, children: [ @@ -127,13 +166,16 @@ class _MaterialPickerState extends State { Color _colorType = _colors[0]; return GestureDetector( onTap: () { - if (widget.onPrimaryChanged != null) widget.onPrimaryChanged!(_colorType); + if (widget.onPrimaryChanged != null) { + widget.onPrimaryChanged!(_colorType); + } setState(() => _currentColorType = _colors); }, child: Container( color: const Color(0x00000000), - padding: - _isPortrait ? const EdgeInsets.fromLTRB(0, 7, 0, 7) : const EdgeInsets.fromLTRB(7, 0, 7, 0), + padding: _isPortrait + ? const EdgeInsets.fromLTRB(0, 7, 0, 7) + : const EdgeInsets.fromLTRB(7, 0, 7, 0), child: Align( child: AnimatedContainer( duration: const Duration(milliseconds: 300), @@ -144,19 +186,28 @@ class _MaterialPickerState extends State { shape: BoxShape.circle, boxShadow: _currentColorType == _colors ? [ - _colorType == Theme.of(context).cardColor - ? BoxShadow( - color: (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38, - blurRadius: 10, - ) - : BoxShadow( - color: _colorType, - blurRadius: 10, - ), - ] + _colorType == Theme.of(context).cardColor + ? BoxShadow( + color: + (Theme.of(context).brightness == + Brightness.light) + ? Colors.grey[300]! + : Colors.black38, + blurRadius: 10, + ) + : BoxShadow( + color: _colorType, + blurRadius: 10, + ), + ] : null, border: _colorType == Theme.of(context).cardColor - ? Border.all(color: (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38, width: 1) + ? Border.all( + color: (Theme.of(context).brightness == + Brightness.light) + ? Colors.grey[300]! + : Colors.black38, + width: 1) : null, ), ), @@ -176,7 +227,8 @@ class _MaterialPickerState extends State { Widget _shadingList() { return ScrollConfiguration( - behavior: ScrollConfiguration.of(context).copyWith(dragDevices: PointerDeviceKind.values.toSet()), + behavior: ScrollConfiguration.of(context) + .copyWith(dragDevices: PointerDeviceKind.values.toSet()), child: ListView( scrollDirection: _isPortrait ? Axis.vertical : Axis.horizontal, children: [ @@ -192,73 +244,95 @@ class _MaterialPickerState extends State { }, child: Container( color: const Color(0x00000000), - margin: _isPortrait ? const EdgeInsets.only(right: 10) : const EdgeInsets.only(bottom: 10), - padding: _isPortrait ? const EdgeInsets.fromLTRB(0, 7, 0, 7) : const EdgeInsets.fromLTRB(7, 0, 7, 0), + margin: _isPortrait + ? const EdgeInsets.only(right: 10) + : const EdgeInsets.only(bottom: 10), + padding: _isPortrait + ? const EdgeInsets.fromLTRB(0, 7, 0, 7) + : const EdgeInsets.fromLTRB(7, 0, 7, 0), child: Align( child: AnimatedContainer( curve: Curves.fastOutSlowIn, duration: const Duration(milliseconds: 500), - width: - _isPortrait ? (_currentShading == _color ? 250 : 230) : (_currentShading == _color ? 50 : 30), + width: _isPortrait + ? (_currentShading == _color ? 250 : 230) + : (_currentShading == _color ? 50 : 30), height: _isPortrait ? 50 : 220, decoration: BoxDecoration( color: _color, boxShadow: _currentShading == _color ? [ - (_color == Colors.white) || (_color == Colors.black) - ? BoxShadow( - color: (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38, - blurRadius: 10, - ) - : BoxShadow( - color: _color, - blurRadius: 10, - ), - ] - : null, - border: (_color == Colors.white) || (_color == Colors.black) - ? Border.all(color: (Theme.of(context).brightness == Brightness.light) ? Colors.grey[300]! : Colors.black38, width: 1) + (_color == Colors.white) || + (_color == Colors.black) + ? BoxShadow( + color: (Theme.of(context).brightness == + Brightness.light) + ? Colors.grey[300]! + : Colors.black38, + blurRadius: 10, + ) + : BoxShadow( + color: _color, + blurRadius: 10, + ), + ] : null, + border: + (_color == Colors.white) || (_color == Colors.black) + ? Border.all( + color: (Theme.of(context).brightness == + Brightness.light) + ? Colors.grey[300]! + : Colors.black38, + width: 1) + : null, ), child: widget.enableLabel ? _isPortrait - ? Row( - children: [ - Text( - ' ${color.values.first}', - style: TextStyle(color: useWhiteForeground(_color) ? Colors.white : Colors.black), - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - '#${(_color.value.toRadixString(16).padLeft(8, '0')).substring(2).toUpperCase()} ', - style: TextStyle( - color: useWhiteForeground(_color) ? Colors.white : Colors.black, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ) - : AnimatedOpacity( - duration: const Duration(milliseconds: 300), - opacity: _currentShading == _color ? 1 : 0, - child: Container( - padding: const EdgeInsets.only(top: 16), - alignment: Alignment.topCenter, - child: Text( - color.values.first, - style: TextStyle( - color: useWhiteForeground(_color) ? Colors.white : Colors.black, - fontWeight: FontWeight.bold, - fontSize: 14, - ), - softWrap: false, - ), - ), - ) + ? Row( + children: [ + Text( + ' ${color.values.first}', + style: TextStyle( + color: useWhiteForeground(_color) + ? Colors.white + : Colors.black), + ), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + '#${(_color.toARGB32().toRadixString(16).padLeft(8, '0')).substring(2).toUpperCase()} ', + style: TextStyle( + color: useWhiteForeground(_color) + ? Colors.white + : Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ) + : AnimatedOpacity( + duration: const Duration(milliseconds: 300), + opacity: _currentShading == _color ? 1 : 0, + child: Container( + padding: const EdgeInsets.only(top: 16), + alignment: Alignment.topCenter, + child: Text( + color.values.first, + style: TextStyle( + color: useWhiteForeground(_color) + ? Colors.white + : Colors.black, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + softWrap: false, + ), + ), + ) : const SizedBox(), ), ), diff --git a/lib/src/palette.dart b/lib/src/palette.dart index 7bc9b33..b259417 100644 --- a/lib/src/palette.dart +++ b/lib/src/palette.dart @@ -3,9 +3,11 @@ // Try to create a Color Picker with other layout on your own :) import 'dart:math'; + import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; + import 'utils.dart'; /// Palette types for color picker area widget. @@ -74,12 +76,15 @@ class HSVWithHueColorPainter extends CustomPainter { ); canvas.drawCircle( - Offset(size.width * hsvColor.saturation, size.height * (1 - hsvColor.value)), + Offset( + size.width * hsvColor.saturation, size.height * (1 - hsvColor.value)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hsvColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hsvColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 - ..blendMode = BlendMode.luminosity ..style = PaintingStyle.stroke, ); } @@ -123,7 +128,10 @@ class HSVWithSaturationColorPainter extends CustomPainter { ), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hsvColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hsvColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -162,7 +170,7 @@ class HSVWithValueColorPainter extends CustomPainter { canvas.drawRect(rect, Paint()..shader = gradientV.createShader(rect)); canvas.drawRect( rect, - Paint()..color = Colors.black.withOpacity(1 - hsvColor.value), + Paint()..color = Colors.black.withValues(alpha: 1 - hsvColor.value), ); canvas.drawCircle( @@ -172,7 +180,10 @@ class HSVWithValueColorPainter extends CustomPainter { ), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hsvColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hsvColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -213,10 +224,14 @@ class HSLWithHueColorPainter extends CustomPainter { canvas.drawRect(rect, Paint()..shader = gradientV.createShader(rect)); canvas.drawCircle( - Offset(size.width * hslColor.saturation, size.height * (1 - hslColor.lightness)), + Offset(size.width * hslColor.saturation, + size.height * (1 - hslColor.lightness)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hslColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hslColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -261,10 +276,14 @@ class HSLWithSaturationColorPainter extends CustomPainter { canvas.drawRect(rect, Paint()..shader = gradientV.createShader(rect)); canvas.drawCircle( - Offset(size.width * hslColor.hue / 360, size.height * (1 - hslColor.lightness)), + Offset(size.width * hslColor.hue / 360, + size.height * (1 - hslColor.lightness)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hslColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hslColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -306,18 +325,26 @@ class HSLWithLightnessColorPainter extends CustomPainter { canvas.drawRect(rect, Paint()..shader = gradientV.createShader(rect)); canvas.drawRect( rect, - Paint()..color = Colors.black.withOpacity((1 - hslColor.lightness * 2).clamp(0, 1)), + Paint() + ..color = Colors.black + .withValues(alpha: (1 - hslColor.lightness * 2).clamp(0, 1)), ); canvas.drawRect( rect, - Paint()..color = Colors.white.withOpacity(((hslColor.lightness - 0.5) * 2).clamp(0, 1)), + Paint() + ..color = Colors.white + .withValues(alpha: ((hslColor.lightness - 0.5) * 2).clamp(0, 1)), ); canvas.drawCircle( - Offset(size.width * hslColor.hue / 360, size.height * (1 - hslColor.saturation)), + Offset(size.width * hslColor.hue / 360, + size.height * (1 - hslColor.saturation)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hslColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hslColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -339,16 +366,16 @@ class RGBWithRedColorPainter extends CustomPainter { final Rect rect = Offset.zero & size; final Gradient gradientH = LinearGradient( colors: [ - Color.fromRGBO(color.red, 255, 0, 1.0), - Color.fromRGBO(color.red, 255, 255, 1.0), + Color.fromRGBO((color.r * 255.0).round() & 0xff, 255, 0, 1.0), + Color.fromRGBO((color.r * 255.0).round() & 0xff, 255, 255, 1.0), ], ); final Gradient gradientV = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color.fromRGBO(color.red, 255, 255, 1.0), - Color.fromRGBO(color.red, 0, 255, 1.0), + Color.fromRGBO((color.r * 255.0).round() & 0xff, 255, 255, 1.0), + Color.fromRGBO((color.r * 255.0).round() & 0xff, 0, 255, 1.0), ], ); canvas.drawRect(rect, Paint()..shader = gradientH.createShader(rect)); @@ -360,10 +387,12 @@ class RGBWithRedColorPainter extends CustomPainter { ); canvas.drawCircle( - Offset(size.width * color.blue / 255, size.height * (1 - color.green / 255)), + Offset(size.width * ((color.b * 255.0).round() & 0xff) / 255, + size.height * (1 - ((color.g * 255.0).round() & 0xff) / 255)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(color) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(color) ? Colors.white : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -385,16 +414,16 @@ class RGBWithGreenColorPainter extends CustomPainter { final Rect rect = Offset.zero & size; final Gradient gradientH = LinearGradient( colors: [ - Color.fromRGBO(255, color.green, 0, 1.0), - Color.fromRGBO(255, color.green, 255, 1.0), + Color.fromRGBO(255, (color.g * 255.0).round() & 0xff, 0, 1.0), + Color.fromRGBO(255, (color.g * 255.0).round() & 0xff, 255, 1.0), ], ); final Gradient gradientV = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color.fromRGBO(255, color.green, 255, 1.0), - Color.fromRGBO(0, color.green, 255, 1.0), + Color.fromRGBO(255, (color.g * 255.0).round() & 0xff, 255, 1.0), + Color.fromRGBO(0, (color.g * 255.0).round() & 0xff, 255, 1.0), ], ); canvas.drawRect(rect, Paint()..shader = gradientH.createShader(rect)); @@ -406,10 +435,12 @@ class RGBWithGreenColorPainter extends CustomPainter { ); canvas.drawCircle( - Offset(size.width * color.blue / 255, size.height * (1 - color.red / 255)), + Offset(size.width * ((color.b * 255.0).round() & 0xff) / 255, + size.height * (1 - ((color.r * 255.0).round() & 0xff) / 255)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(color) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(color) ? Colors.white : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -431,16 +462,16 @@ class RGBWithBlueColorPainter extends CustomPainter { final Rect rect = Offset.zero & size; final Gradient gradientH = LinearGradient( colors: [ - Color.fromRGBO(0, 255, color.blue, 1.0), - Color.fromRGBO(255, 255, color.blue, 1.0), + Color.fromRGBO(0, 255, (color.b * 255.0).round() & 0xff, 1.0), + Color.fromRGBO(255, 255, (color.b * 255.0).round() & 0xff, 1.0), ], ); final Gradient gradientV = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Color.fromRGBO(255, 255, color.blue, 1.0), - Color.fromRGBO(255, 0, color.blue, 1.0), + Color.fromRGBO(255, 255, (color.b * 255.0).round() & 0xff, 1.0), + Color.fromRGBO(255, 0, (color.b * 255.0).round() & 0xff, 1.0), ], ); canvas.drawRect(rect, Paint()..shader = gradientH.createShader(rect)); @@ -452,10 +483,12 @@ class RGBWithBlueColorPainter extends CustomPainter { ); canvas.drawCircle( - Offset(size.width * color.red / 255, size.height * (1 - color.green / 255)), + Offset(size.width * ((color.r * 255.0).round() & 0xff) / 255, + size.height * (1 - ((color.g * 255.0).round() & 0xff) / 255)), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(color) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(color) ? Colors.white : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -494,18 +527,26 @@ class HUEColorWheelPainter extends CustomPainter { Color(0x00FFFFFF), ], ); - canvas.drawCircle(center, radio, Paint()..shader = gradientS.createShader(rect)); - canvas.drawCircle(center, radio, Paint()..shader = gradientR.createShader(rect)); - canvas.drawCircle(center, radio, Paint()..color = Colors.black.withOpacity(1 - hsvColor.value)); + canvas.drawCircle( + center, radio, Paint()..shader = gradientS.createShader(rect)); + canvas.drawCircle( + center, radio, Paint()..shader = gradientR.createShader(rect)); + canvas.drawCircle(center, radio, + Paint()..color = Colors.black.withValues(alpha: 1 - hsvColor.value)); canvas.drawCircle( Offset( - center.dx + hsvColor.saturation * radio * cos((hsvColor.hue * pi / 180)), - center.dy - hsvColor.saturation * radio * sin((hsvColor.hue * pi / 180)), + center.dx + + hsvColor.saturation * radio * cos((hsvColor.hue * pi / 180)), + center.dy - + hsvColor.saturation * radio * sin((hsvColor.hue * pi / 180)), ), size.height * 0.04, Paint() - ..color = pointerColor ?? (useWhiteForeground(hsvColor.toColor()) ? Colors.white : Colors.black) + ..color = pointerColor ?? + (useWhiteForeground(hsvColor.toColor()) + ? Colors.white + : Colors.black) ..strokeWidth = 1.5 ..style = PaintingStyle.stroke, ); @@ -517,7 +558,8 @@ class HUEColorWheelPainter extends CustomPainter { /// Painter for hue ring. class HueRingPainter extends CustomPainter { - const HueRingPainter(this.hsvColor, {this.displayThumbColor = true, this.strokeWidth = 5}); + const HueRingPainter(this.hsvColor, + {this.displayThumbColor = true, this.strokeWidth = 5}); final HSVColor hsvColor; final bool displayThumbColor; @@ -551,7 +593,11 @@ class HueRingPainter extends CustomPainter { center.dx + radio * cos((hsvColor.hue * pi / 180)), center.dy - radio * sin((hsvColor.hue * pi / 180)), ); - canvas.drawShadow(Path()..addOval(Rect.fromCircle(center: offset, radius: 12)), Colors.black, 3.0, true); + canvas.drawShadow( + Path()..addOval(Rect.fromCircle(center: offset, radius: 12)), + Colors.black, + 3.0, + true); canvas.drawCircle( offset, size.height * 0.04, @@ -678,32 +724,32 @@ class TrackPainter extends CustomPainter { break; case TrackType.red: final List colors = [ - hsvColor.toColor().withRed(0).withOpacity(1.0), - hsvColor.toColor().withRed(255).withOpacity(1.0), + hsvColor.toColor().withRed(0).withValues(alpha: 1.0), + hsvColor.toColor().withRed(255).withValues(alpha: 1.0), ]; Gradient gradient = LinearGradient(colors: colors); canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect)); break; case TrackType.green: final List colors = [ - hsvColor.toColor().withGreen(0).withOpacity(1.0), - hsvColor.toColor().withGreen(255).withOpacity(1.0), + hsvColor.toColor().withGreen(0).withValues(alpha: 1.0), + hsvColor.toColor().withGreen(255).withValues(alpha: 1.0), ]; Gradient gradient = LinearGradient(colors: colors); canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect)); break; case TrackType.blue: final List colors = [ - hsvColor.toColor().withBlue(0).withOpacity(1.0), - hsvColor.toColor().withBlue(255).withOpacity(1.0), + hsvColor.toColor().withBlue(0).withValues(alpha: 1.0), + hsvColor.toColor().withBlue(255).withValues(alpha: 1.0), ]; Gradient gradient = LinearGradient(colors: colors); canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect)); break; case TrackType.alpha: final List colors = [ - hsvColor.toColor().withOpacity(0.0), - hsvColor.toColor().withOpacity(1.0), + hsvColor.toColor().withValues(alpha: 0.0), + hsvColor.toColor().withValues(alpha: 1.0), ]; Gradient gradient = LinearGradient(colors: colors); canvas.drawRect(rect, Paint()..shader = gradient.createShader(rect)); @@ -727,7 +773,8 @@ class ThumbPainter extends CustomPainter { canvas.drawShadow( Path() ..addOval( - Rect.fromCircle(center: const Offset(0.5, 2.0), radius: size.width * 1.8), + Rect.fromCircle( + center: const Offset(0.5, 2.0), radius: size.width * 1.8), ), Colors.black, 3.0, @@ -814,7 +861,11 @@ class ColorPickerLabel extends StatefulWidget { this.hsvColor, { Key? key, this.enableAlpha = true, - this.colorLabelTypes = const [ColorLabelType.rgb, ColorLabelType.hsv, ColorLabelType.hsl], + this.colorLabelTypes = const [ + ColorLabelType.rgb, + ColorLabelType.hsv, + ColorLabelType.hsl + ], this.textStyle, }) : assert(colorLabelTypes.length > 0), super(key: key); @@ -848,18 +899,30 @@ class _ColorPickerLabelState extends State { if (colorLabelType == ColorLabelType.hex) { final Color color = hsvColor.toColor(); return [ - color.red.toRadixString(16).toUpperCase().padLeft(2, '0'), - color.green.toRadixString(16).toUpperCase().padLeft(2, '0'), - color.blue.toRadixString(16).toUpperCase().padLeft(2, '0'), - color.alpha.toRadixString(16).toUpperCase().padLeft(2, '0'), + ((color.r * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0'), + ((color.g * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0'), + ((color.b * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0'), + ((color.a * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0'), ]; } else if (colorLabelType == ColorLabelType.rgb) { final Color color = hsvColor.toColor(); return [ - color.red.toString(), - color.green.toString(), - color.blue.toString(), - '${(color.opacity * 100).round()}%', + ((color.r * 255.0).round() & 0xff).toString(), + ((color.g * 255.0).round() & 0xff).toString(), + ((color.b * 255.0).round() & 0xff).toString(), + '${(color.a * 100).round()}%', ]; } else if (colorLabelType == ColorLabelType.hsv) { return [ @@ -883,7 +946,9 @@ class _ColorPickerLabelState extends State { List colorValueLabels() { double fontSize = 14; - if (widget.textStyle != null && widget.textStyle?.fontSize != null) fontSize = widget.textStyle?.fontSize ?? 14; + if (widget.textStyle != null && widget.textStyle?.fontSize != null) { + fontSize = widget.textStyle?.fontSize ?? 14; + } return [ for (String item in _colorTypes[_colorType] ?? []) @@ -897,14 +962,17 @@ class _ColorPickerLabelState extends State { children: [ Text( item, - style: widget.textStyle ?? Theme.of(context).textTheme.bodyLarge, + style: widget.textStyle ?? + Theme.of(context).textTheme.bodyLarge, ), const SizedBox(height: 10.0), Expanded( child: Text( - colorValue(widget.hsvColor, _colorType)[_colorTypes[_colorType]!.indexOf(item)], + colorValue(widget.hsvColor, _colorType)[ + _colorTypes[_colorType]!.indexOf(item)], overflow: TextOverflow.ellipsis, - style: widget.textStyle ?? Theme.of(context).textTheme.bodyMedium, + style: widget.textStyle ?? + Theme.of(context).textTheme.bodyMedium, ), ), ], @@ -970,18 +1038,33 @@ class _ColorPickerInputState extends State { @override Widget build(BuildContext context) { - if (inputColor != widget.color.value) { + if (inputColor != widget.color.toARGB32()) { // ignore: prefer_interpolation_to_compose_strings textEditingController.text = '#' + - widget.color.red.toRadixString(16).toUpperCase().padLeft(2, '0') + - widget.color.green.toRadixString(16).toUpperCase().padLeft(2, '0') + - widget.color.blue.toRadixString(16).toUpperCase().padLeft(2, '0') + - (widget.enableAlpha ? widget.color.alpha.toRadixString(16).toUpperCase().padLeft(2, '0') : ''); + ((widget.color.r * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0') + + ((widget.color.g * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0') + + ((widget.color.b * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0') + + (widget.enableAlpha + ? ((widget.color.a * 255.0).round() & 0xff) + .toRadixString(16) + .toUpperCase() + .padLeft(2, '0') + : ''); } return Padding( padding: const EdgeInsets.only(top: 5.0), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - if (!widget.embeddedText) Text('Hex', style: Theme.of(context).textTheme.bodyLarge), + if (!widget.embeddedText) + Text('Hex', style: Theme.of(context).textTheme.bodyLarge), const SizedBox(width: 10), SizedBox( width: (Theme.of(context).textTheme.bodyMedium?.fontSize ?? 14) * 10, @@ -1000,12 +1083,13 @@ class _ColorPickerInputState extends State { onChanged: (String value) { String input = value; if (value.length == 9) { - input = value.split('').getRange(7, 9).join() + value.split('').getRange(1, 7).join(); + input = value.split('').getRange(7, 9).join() + + value.split('').getRange(1, 7).join(); } final Color? color = colorFromHex(input); if (color != null) { widget.onColorChanged(color); - inputColor = color.value; + inputColor = color.toARGB32(); } }, ), @@ -1034,7 +1118,8 @@ class ColorPickerSlider extends StatelessWidget { void slideEvent(RenderBox getBox, BoxConstraints box, Offset globalPosition) { double localDx = getBox.globalToLocal(globalPosition).dx - 15.0; - double progress = localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0); + double progress = + localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0); switch (trackType) { case TrackType.hue: // 360 is the same as zero @@ -1054,16 +1139,20 @@ class ColorPickerSlider extends StatelessWidget { onColorChanged(hslToHsv(hsvToHsl(hsvColor).withLightness(progress))); break; case TrackType.red: - onColorChanged(HSVColor.fromColor(hsvColor.toColor().withRed((progress * 0xff).round()))); + onColorChanged(HSVColor.fromColor( + hsvColor.toColor().withRed((progress * 0xff).round()))); break; case TrackType.green: - onColorChanged(HSVColor.fromColor(hsvColor.toColor().withGreen((progress * 0xff).round()))); + onColorChanged(HSVColor.fromColor( + hsvColor.toColor().withGreen((progress * 0xff).round()))); break; case TrackType.blue: - onColorChanged(HSVColor.fromColor(hsvColor.toColor().withBlue((progress * 0xff).round()))); + onColorChanged(HSVColor.fromColor( + hsvColor.toColor().withBlue((progress * 0xff).round()))); break; case TrackType.alpha: - onColorChanged(hsvColor.withAlpha(localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0))); + onColorChanged(hsvColor.withAlpha( + localDx.clamp(0.0, box.maxWidth - 30.0) / (box.maxWidth - 30.0))); break; } } @@ -1080,35 +1169,49 @@ class ColorPickerSlider extends StatelessWidget { break; case TrackType.saturation: thumbOffset += (box.maxWidth - 30.0) * hsvColor.saturation; - thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, hsvColor.saturation, 1.0).toColor(); + thumbColor = + HSVColor.fromAHSV(1.0, hsvColor.hue, hsvColor.saturation, 1.0) + .toColor(); break; case TrackType.saturationForHSL: thumbOffset += (box.maxWidth - 30.0) * hsvToHsl(hsvColor).saturation; - thumbColor = HSLColor.fromAHSL(1.0, hsvColor.hue, hsvToHsl(hsvColor).saturation, 0.5).toColor(); + thumbColor = HSLColor.fromAHSL( + 1.0, hsvColor.hue, hsvToHsl(hsvColor).saturation, 0.5) + .toColor(); break; case TrackType.value: thumbOffset += (box.maxWidth - 30.0) * hsvColor.value; - thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, hsvColor.value).toColor(); + thumbColor = HSVColor.fromAHSV(1.0, hsvColor.hue, 1.0, hsvColor.value) + .toColor(); break; case TrackType.lightness: thumbOffset += (box.maxWidth - 30.0) * hsvToHsl(hsvColor).lightness; - thumbColor = HSLColor.fromAHSL(1.0, hsvColor.hue, 1.0, hsvToHsl(hsvColor).lightness).toColor(); + thumbColor = HSLColor.fromAHSL( + 1.0, hsvColor.hue, 1.0, hsvToHsl(hsvColor).lightness) + .toColor(); break; case TrackType.red: - thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().red / 0xff; - thumbColor = hsvColor.toColor().withOpacity(1.0); + thumbOffset += (box.maxWidth - 30.0) * + ((hsvColor.toColor().r * 255.0).round() & 0xff) / + 0xff; + thumbColor = hsvColor.toColor().withValues(alpha: 1.0); break; case TrackType.green: - thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().green / 0xff; - thumbColor = hsvColor.toColor().withOpacity(1.0); + thumbOffset += (box.maxWidth - 30.0) * + ((hsvColor.toColor().g * 255.0).round() & 0xff) / + 0xff; + thumbColor = hsvColor.toColor().withValues(alpha: 1.0); break; case TrackType.blue: - thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().blue / 0xff; - thumbColor = hsvColor.toColor().withOpacity(1.0); + thumbOffset += (box.maxWidth - 30.0) * + ((hsvColor.toColor().b * 255.0).round() & 0xff) / + 0xff; + thumbColor = hsvColor.toColor().withValues(alpha: 1.0); break; case TrackType.alpha: - thumbOffset += (box.maxWidth - 30.0) * hsvColor.toColor().opacity; - thumbColor = hsvColor.toColor().withOpacity(hsvColor.alpha); + thumbOffset += (box.maxWidth - 30.0) * + ((hsvColor.toColor().a * 255.0).round() / 0xff); + thumbColor = hsvColor.toColor().withValues(alpha: hsvColor.alpha); break; } @@ -1144,10 +1247,12 @@ class ColorPickerSlider extends StatelessWidget { builder: (BuildContext context, BoxConstraints box) { RenderBox? getBox = context.findRenderObject() as RenderBox?; return GestureDetector( - onPanDown: (DragDownDetails details) => - getBox != null ? slideEvent(getBox, box, details.globalPosition) : null, - onPanUpdate: (DragUpdateDetails details) => - getBox != null ? slideEvent(getBox, box, details.globalPosition) : null, + onPanDown: (DragDownDetails details) => getBox != null + ? slideEvent(getBox, box, details.globalPosition) + : null, + onPanUpdate: (DragUpdateDetails details) => getBox != null + ? slideEvent(getBox, box, details.globalPosition) + : null, ); }, ), @@ -1211,7 +1316,8 @@ class ColorPickerArea extends StatelessWidget { onColorChanged(hsvColor.withHue(horizontal * 360).withValue(vertical)); break; case PaletteType.hsvWithValue: - onColorChanged(hsvColor.withHue(horizontal * 360).withSaturation(vertical)); + onColorChanged( + hsvColor.withHue(horizontal * 360).withSaturation(vertical)); break; case PaletteType.hsl: case PaletteType.hslWithHue: @@ -1231,17 +1337,26 @@ class ColorPickerArea extends StatelessWidget { break; case PaletteType.rgbWithRed: onColorChanged(HSVColor.fromColor( - hsvColor.toColor().withBlue((horizontal * 255).round()).withGreen((vertical * 255).round()), + hsvColor + .toColor() + .withBlue((horizontal * 255).round()) + .withGreen((vertical * 255).round()), )); break; case PaletteType.rgbWithGreen: onColorChanged(HSVColor.fromColor( - hsvColor.toColor().withBlue((horizontal * 255).round()).withRed((vertical * 255).round()), + hsvColor + .toColor() + .withBlue((horizontal * 255).round()) + .withRed((vertical * 255).round()), )); break; case PaletteType.rgbWithBlue: onColorChanged(HSVColor.fromColor( - hsvColor.toColor().withRed((horizontal * 255).round()).withGreen((vertical * 255).round()), + hsvColor + .toColor() + .withRed((horizontal * 255).round()) + .withGreen((vertical * 255).round()), )); break; default: @@ -1253,7 +1368,8 @@ class ColorPickerArea extends StatelessWidget { onColorChanged(hsvColor.withHue(hue).withSaturation(radio)); } - void _handleGesture(Offset position, BuildContext context, double height, double width) { + void _handleGesture( + Offset position, BuildContext context, double height, double width) { RenderBox? getBox = context.findRenderObject() as RenderBox?; if (getBox == null) return; @@ -1264,9 +1380,15 @@ class ColorPickerArea extends StatelessWidget { if (paletteType == PaletteType.hueWheel) { Offset center = Offset(width / 2, height / 2); double radio = width <= height ? width / 2 : height / 2; - double dist = sqrt(pow(horizontal - center.dx, 2) + pow(vertical - center.dy, 2)) / radio; - double rad = (atan2(horizontal - center.dx, vertical - center.dy) / pi + 1) / 2 * 360; - _handleColorWheelChange(((rad + 90) % 360).clamp(0, 360), dist.clamp(0, 1)); + double dist = + sqrt(pow(horizontal - center.dx, 2) + pow(vertical - center.dy, 2)) / + radio; + double rad = + (atan2(horizontal - center.dx, vertical - center.dy) / pi + 1) / + 2 * + 360; + _handleColorWheelChange( + ((rad + 90) % 360).clamp(0, 360), dist.clamp(0, 1)); } else { _handleColorRectChange(horizontal / width, 1 - vertical / height); } @@ -1281,12 +1403,16 @@ class ColorPickerArea extends StatelessWidget { return RawGestureDetector( gestures: { - _AlwaysWinPanGestureRecognizer: GestureRecognizerFactoryWithHandlers<_AlwaysWinPanGestureRecognizer>( + _AlwaysWinPanGestureRecognizer: + GestureRecognizerFactoryWithHandlers< + _AlwaysWinPanGestureRecognizer>( () => _AlwaysWinPanGestureRecognizer(), (_AlwaysWinPanGestureRecognizer instance) { instance - ..onDown = ((details) => _handleGesture(details.globalPosition, context, height, width)) - ..onUpdate = ((details) => _handleGesture(details.globalPosition, context, height, width)); + ..onDown = ((details) => _handleGesture( + details.globalPosition, context, height, width)) + ..onUpdate = ((details) => _handleGesture( + details.globalPosition, context, height, width)); }, ), }, @@ -1297,22 +1423,32 @@ class ColorPickerArea extends StatelessWidget { case PaletteType.hsvWithHue: return CustomPaint(painter: HSVWithHueColorPainter(hsvColor)); case PaletteType.hsvWithSaturation: - return CustomPaint(painter: HSVWithSaturationColorPainter(hsvColor)); + return CustomPaint( + painter: HSVWithSaturationColorPainter(hsvColor)); case PaletteType.hsvWithValue: - return CustomPaint(painter: HSVWithValueColorPainter(hsvColor)); + return CustomPaint( + painter: HSVWithValueColorPainter(hsvColor)); case PaletteType.hsl: case PaletteType.hslWithHue: - return CustomPaint(painter: HSLWithHueColorPainter(hsvToHsl(hsvColor))); + return CustomPaint( + painter: HSLWithHueColorPainter(hsvToHsl(hsvColor))); case PaletteType.hslWithSaturation: - return CustomPaint(painter: HSLWithSaturationColorPainter(hsvToHsl(hsvColor))); + return CustomPaint( + painter: + HSLWithSaturationColorPainter(hsvToHsl(hsvColor))); case PaletteType.hslWithLightness: - return CustomPaint(painter: HSLWithLightnessColorPainter(hsvToHsl(hsvColor))); + return CustomPaint( + painter: + HSLWithLightnessColorPainter(hsvToHsl(hsvColor))); case PaletteType.rgbWithRed: - return CustomPaint(painter: RGBWithRedColorPainter(hsvColor.toColor())); + return CustomPaint( + painter: RGBWithRedColorPainter(hsvColor.toColor())); case PaletteType.rgbWithGreen: - return CustomPaint(painter: RGBWithGreenColorPainter(hsvColor.toColor())); + return CustomPaint( + painter: RGBWithGreenColorPainter(hsvColor.toColor())); case PaletteType.rgbWithBlue: - return CustomPaint(painter: RGBWithBlueColorPainter(hsvColor.toColor())); + return CustomPaint( + painter: RGBWithBlueColorPainter(hsvColor.toColor())); case PaletteType.hueWheel: return CustomPaint(painter: HUEColorWheelPainter(hsvColor)); default: @@ -1341,7 +1477,8 @@ class ColorPickerHueRing extends StatelessWidget { final bool displayThumbColor; final double strokeWidth; - void _handleGesture(Offset position, BuildContext context, double height, double width) { + void _handleGesture( + Offset position, BuildContext context, double height, double width) { RenderBox? getBox = context.findRenderObject() as RenderBox?; if (getBox == null) return; @@ -1351,9 +1488,16 @@ class ColorPickerHueRing extends StatelessWidget { Offset center = Offset(width / 2, height / 2); double radio = width <= height ? width / 2 : height / 2; - double dist = sqrt(pow(horizontal - center.dx, 2) + pow(vertical - center.dy, 2)) / radio; - double rad = (atan2(horizontal - center.dx, vertical - center.dy) / pi + 1) / 2 * 360; - if (dist > 0.7 && dist < 1.3) onColorChanged(hsvColor.withHue(((rad + 90) % 360).clamp(0, 360))); + double dist = + sqrt(pow(horizontal - center.dx, 2) + pow(vertical - center.dy, 2)) / + radio; + double rad = + (atan2(horizontal - center.dx, vertical - center.dy) / pi + 1) / + 2 * + 360; + if (dist > 0.7 && dist < 1.3) { + onColorChanged(hsvColor.withHue(((rad + 90) % 360).clamp(0, 360))); + } } @override @@ -1365,17 +1509,22 @@ class ColorPickerHueRing extends StatelessWidget { return RawGestureDetector( gestures: { - _AlwaysWinPanGestureRecognizer: GestureRecognizerFactoryWithHandlers<_AlwaysWinPanGestureRecognizer>( + _AlwaysWinPanGestureRecognizer: + GestureRecognizerFactoryWithHandlers< + _AlwaysWinPanGestureRecognizer>( () => _AlwaysWinPanGestureRecognizer(), (_AlwaysWinPanGestureRecognizer instance) { instance - ..onDown = ((details) => _handleGesture(details.globalPosition, context, height, width)) - ..onUpdate = ((details) => _handleGesture(details.globalPosition, context, height, width)); + ..onDown = ((details) => _handleGesture( + details.globalPosition, context, height, width)) + ..onUpdate = ((details) => _handleGesture( + details.globalPosition, context, height, width)); }, ), }, child: CustomPaint( - painter: HueRingPainter(hsvColor, displayThumbColor: displayThumbColor, strokeWidth: strokeWidth), + painter: HueRingPainter(hsvColor, + displayThumbColor: displayThumbColor, strokeWidth: strokeWidth), ), ); }, @@ -1398,5 +1547,6 @@ class _AlwaysWinPanGestureRecognizer extends PanGestureRecognizer { class UpperCaseTextFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate(oldValue, TextEditingValue newValue) => - TextEditingValue(text: newValue.text.toUpperCase(), selection: newValue.selection); + TextEditingValue( + text: newValue.text.toUpperCase(), selection: newValue.selection); } diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 9cda875..8dd7bf4 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -1,7 +1,9 @@ // Common function lib import 'dart:math'; + import 'package:flutter/painting.dart'; + import 'colors.dart'; /// Check if is good condition to use white foreground color by passing @@ -17,9 +19,9 @@ bool useWhiteForeground(Color backgroundColor, {double bias = 0.0}) { // return 1.05 / (color.computeLuminance() + 0.05) > 4.5; // New: - int v = sqrt(pow(backgroundColor.red, 2) * 0.299 + - pow(backgroundColor.green, 2) * 0.587 + - pow(backgroundColor.blue, 2) * 0.114) + int v = sqrt(pow((backgroundColor.r * 255.0).round() & 0xff, 2) * 0.299 + + pow((backgroundColor.g * 255.0).round() & 0xff, 2) * 0.587 + + pow((backgroundColor.b * 255.0).round() & 0xff, 2) * 0.114) .round(); return v < 130 + bias ? true : false; } @@ -55,7 +57,9 @@ HSVColor hslToHsv(HSLColor color) { double s = 0.0; double v = 0.0; - v = color.lightness + color.saturation * (color.lightness < 0.5 ? color.lightness : 1 - color.lightness); + v = color.lightness + + color.saturation * + (color.lightness < 0.5 ? color.lightness : 1 - color.lightness); if (v != 0) s = 2 - 2 * color.lightness / v; return HSVColor.fromAHSV( @@ -92,7 +96,8 @@ const String kValidHexPattern = r'^#?[0-9a-fA-F]{1,8}'; /// if (hexCompleteValidator.hasMatch(hex)) print('$hex is valid HEX color'); /// ``` /// Reference: https://en.wikipedia.org/wiki/Web_colors#Hex_triplet -const String kCompleteValidHexPattern = r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$'; +const String kCompleteValidHexPattern = + r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$'; /// Try to convert text input or any [String] to valid [Color]. /// The [String] must be provided in one of those formats: @@ -189,10 +194,10 @@ String colorToHex( bool toUpperCase = true, }) { final String hex = (includeHashSign ? '#' : '') + - (enableAlpha ? _padRadix(color.alpha) : '') + - _padRadix(color.red) + - _padRadix(color.green) + - _padRadix(color.blue); + (enableAlpha ? _padRadix((color.a * 255.0).round() & 0xff) : '') + + _padRadix((color.r * 255.0).round() & 0xff) + + _padRadix((color.g * 255.0).round() & 0xff) + + _padRadix((color.b * 255.0).round() & 0xff); return toUpperCase ? hex.toUpperCase() : hex; } diff --git a/pubspec.lock b/pubspec.lock index 6f0b067..69bf3fb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,50 +5,50 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -71,18 +71,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.9" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -103,87 +103,87 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.16.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.4" vector_math: dependency: transitive description: @@ -196,10 +196,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "15.0.0" sdks: - dart: ">=3.3.0 <4.0.0" + dart: ">=3.7.0-0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54"