FlexColorPicker

repository·master·Indexed 42 days ago

https://github.com/rastislavmirek/flexcolorpicker

A highly customizable and hackable color picker library for Swift 5. It supports HSB and RGB color models with radial and rectangular palettes, offering integration via DefaultColorPickerViewController or custom implementations using the ColorControl protocol.

Tokens
2.4K
Snippets
7
Records
13
Agent score
4%

What's inside FlexColorPicker

  1. Customize color picker layout and controls

    master

    For more flexibility than the DefaultColorPickerViewController, you can build a custom picker by manually selecting and arranging ColorControls.

    Core Components

    • Color Controls: UIViews (usually subclassing UIControl) that allow users to pick colors (e.g., sliders, palettes).
    • Color Picker Controllers: Objects that manage and synchronize multiple color controls so they all reflect the same selected color.

    Implementation Approaches

    1. Custom Layout: Choose specific controls (like RadialPaletteControl or RedSliderControl) and arrange them in your own view hierarchy.
    2. Custom Look/Behavior: Implement the ColorControl protocol or subclass existing controls to change how they appear or react to input.
    3. Combined: Use custom controls within a custom layout.
  2. Use DefaultColorPickerViewController via Storyboard

    master
    1. In your Storyboard, set the Class of your view controller to DefaultColorPickerViewController using the Identity Inspector under Custom Class.
    2. Customize the controller using properties available in the Attributes Inspector.
    3. Set the delegate in code (e.g., in prepare(for:sender:)) because the delegate cannot be set directly in Storyboard:
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destinationColorPicker = segue.destination as? ColorPickerControllerProtocol {
            destinationColorPicker.delegate = self
        }
    }
  3. Connect color controls to a controller

    master

    To make multiple controls work together, they must be connected to a ColorPickerController (or its convenience wrapper CustomColorPickerViewController). When connected, selecting a color in one control automatically updates all other controls managed by that same controller.

    Using Storyboard

    1. Lay out your controls in the storyboard.
    2. Set the class of each control in the Identity Inspector (e.g., set to RadialPaletteControl).
    3. Set the controller's class to CustomColorPickerViewController.
    4. Open the Connection Inspector and connect the control outlets to your laid-out views.

    Using Code

    If you cannot subclass CustomColorPickerViewController (e.g., due to existing inheritance), use ColorPickerController directly. You can add controls programmatically using:

    colorPickerController.addControl(yourCustomControl)
  4. Install FlexColorPicker via Swift Package Manager

    master

    To add FlexColorPicker to your Xcode project using SPM:

    1. In Xcode 11+, go to File → Swift Packages → Add Package Dependency....
    2. Enter the repository URL: https://github.com/RastislavMirek/FlexColorPicker.
    3. Set your version preference and confirm.

    If you are using a Package.swift file, add the following dependency:

    dependencies: [
        .package(url: "https://github.com/RastislavMirek/FlexColorPicker.git", from: "1.3.1")
    ]
  5. Install FlexColorPicker via Direct Installation

    master

    If you are not using SPM or Cocoapods:

    1. Clone the repository:
      git clone https://github.com/RastislavMirek/FlexColorPicker
      Or download the latest release ZIP from GitHub releases.
    2. Open the project in Xcode and compile the FlexColorPicker target.
    3. Locate the FlexColorPicker.framework in the Products directory.
    4. In your own project, select your application target, go to the General tab, and add FlexColorPicker.framework under the Embedded Binaries section.
    git clone https://github.com/RastislavMirek/FlexColorPicker
  6. Handle gesture conflicts in ScrollViews or Modal Views

    master

    Because color controls often use pan gestures, they may conflict with UIScrollView scrolling or iOS 13 modal dismissal gestures.

    Fix for Custom Controls (Non-AbstractColorControl)

    If your custom control does not inherit from AbstractColorControl, add this to the view receiving touches to prevent pan gestures from blocking dismissal/scrolling:

    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return !(gestureRecognizer is UIPanGestureRecognizer)
    }

    Fix for Subviews within a Color Control

    If you add a subview to a color control and want to ensure interaction doesn't conflict with the parent's scrolling/dismissal, implement the following in the subview:

    weak var delegate: LimitedGestureViewDelegate?
    
    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        guard let delegate = delegate else { 
            return !(gestureRecognizer is UIPanGestureRecognizer) 
        }
        return delegate.gestureRecognizerShouldBegin(gestureRecognizer)
    }
  7. Use DefaultColorPickerViewController via Code

    master

    You can instantiate and present the color picker programmatically.

    To push onto a Navigation Controller:

    let colorPickerController = DefaultColorPickerViewController()
    colorPickerController.delegate = self
    navigationController?.pushViewController(colorPickerController, animated: true)

    To present Modally:

    let colorPickerController = DefaultColorPickerViewController()
    colorPickerController.delegate = self
    let navigationController = UINavigationController(rootViewController: colorPickerController)
    present(navigationController, animated: true, completion: nil)
  8. Configure ColorPreviewWithHex tap behavior

    master

    The ColorPreviewWithHex control can be tapped to trigger a selection event. When tapped, the ColorPickerController calls ColorPickerDelegate.colorPicker(_:selectedColor:usingControl:) on its delegate.

    To disable this behavior, set the tapToConfirm property to false:

    colorPreviewControl.tapToConfirm = false
  9. Implement ColorPickerDelegate to receive color updates

    master

    To receive notifications when a user selects or confirms a color using DefaultColorPickerViewController, implement the ColorPickerDelegate protocol in your controller. Both methods are optional.

    • colorPicker(_:selectedColor:usingControl:): Called when the user selects a color (before confirmation). Use this if you want to update UI elements in real-time.
    • colorPicker(_:confirmedColor:usingControl:): Called when the user confirms their selection.
    // MyController is the controller that presents DefaultColorPickerViewController
    extension MyController: ColorPickerDelegate {
    
        func colorPicker(_ colorPicker: ColorPickerController, selectedColor: UIColor, usingControl: ColorControl) {
            // code to handle that user selected a color without confirmed it yet (may change selected color)  
        }
        
        func colorPicker(_ colorPicker: ColorPickerController, confirmedColor: UIColor, usingControl: ColorControl) {
            // code to handle that user has confirmed selected color
        }
    }
  10. Configure Rectangular Palette in DefaultColorPickerViewController

    master

    By default, the picker uses a radial hue-saturation palette. You can switch to a rectangular palette by setting useRadialPalette to false on the DefaultColorPickerViewController instance.

    When using a rectangular palette, you can also configure:

    • rectangularPaletteBorderOn
    • rectangularPaletteHueHorizontalInPortrait
    • rectangularPaletteHueHorizontalInLandscape

    Refer to the in-code documentation for specific property details.

    colorPickerController.useRadialPalette = false
  11. Extend or override color controls

    master

    You can extend the library's functionality by implementing the ColorControl protocol or subclassing specific base classes:

    • AbstractColorControl: The base class for all controls. Always subclass this if possible.
    • AdjustedHitBoxColorControl: Provides an extended hit box margin around the control.
    • ColorSliderControl: Use this if you need sliders for color models other than HSB or RGB.
    • ColorPaletteControl: Use this to create entirely new types of color palettes.

    Using Delegates for Customization

    Instead of subclassing ColorSliderControl or ColorPaletteControl, you can often achieve the desired look and behavior by implementing their respective delegates:

    • ColorSliderDelegate
    • ColorPaletteDelegate