mirror of
https://github.com/joncardasis/ChromaColorPicker.git
synced 2024-11-29 02:56:30 +03:00
Updated example project. Refactored and updated uicontrol classes. Brightness slider now attaches to a ChromaColorPicker instance via the connect method.
This commit is contained in:
parent
923497892e
commit
1eb6bd5d23
@ -18,7 +18,7 @@
|
||||
FC1BD8C02207D7B700817AF3 /* ChromaColorPickerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerTests.swift */; };
|
||||
FC1BD8C22207D7B700817AF3 /* ChromaColorPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3503B82F1F2689BC00750356 /* ChromaColorPicker.framework */; };
|
||||
FC4387C422603AE900F739F1 /* ColorWheelViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCCA42AB226038A400BE2FF9 /* ColorWheelViewTests.swift */; };
|
||||
FC4387C62262556600F739F1 /* BrightnessSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4387C52262556600F739F1 /* BrightnessSlider.swift */; };
|
||||
FC4387C62262556600F739F1 /* ChromaBrightnessSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4387C52262556600F739F1 /* ChromaBrightnessSlider.swift */; };
|
||||
FC4387C922625C7000F739F1 /* SliderTrackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4387C822625C7000F739F1 /* SliderTrackView.swift */; };
|
||||
FC4387CB22625DA800F739F1 /* SliderHandleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4387CA22625DA800F739F1 /* SliderHandleView.swift */; };
|
||||
FC4387CD2262B82600F739F1 /* ChromaControlStylable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4387CC2262B82600F739F1 /* ChromaControlStylable.swift */; };
|
||||
@ -79,7 +79,7 @@
|
||||
FC1BD8CB2207FCE100817AF3 /* UIColor+Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Utilities.swift"; sourceTree = "<group>"; };
|
||||
FC1BD8CC2207FCE100817AF3 /* ChromaAddButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChromaAddButton.swift; sourceTree = "<group>"; };
|
||||
FC1BD8CD2207FCE100817AF3 /* ColorModeToggleButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorModeToggleButton.swift; sourceTree = "<group>"; };
|
||||
FC4387C52262556600F739F1 /* BrightnessSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrightnessSlider.swift; sourceTree = "<group>"; };
|
||||
FC4387C52262556600F739F1 /* ChromaBrightnessSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaBrightnessSlider.swift; sourceTree = "<group>"; };
|
||||
FC4387C822625C7000F739F1 /* SliderTrackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderTrackView.swift; sourceTree = "<group>"; };
|
||||
FC4387CA22625DA800F739F1 /* SliderHandleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderHandleView.swift; sourceTree = "<group>"; };
|
||||
FC4387CC2262B82600F739F1 /* ChromaControlStylable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaControlStylable.swift; sourceTree = "<group>"; };
|
||||
@ -126,9 +126,8 @@
|
||||
3503B8311F2689BC00750356 /* ChromaColorPicker.h */,
|
||||
3503B8321F2689BC00750356 /* Info.plist */,
|
||||
FCEA4E262235AAA200C0A1B6 /* ChromaColorPicker.swift */,
|
||||
FCCA42A6226023F000BE2FF9 /* ChromaColorHandle.swift */,
|
||||
FC4387C52262556600F739F1 /* ChromaBrightnessSlider.swift */,
|
||||
FCCA42A4226022A800BE2FF9 /* ColorWheelView.swift */,
|
||||
FC4387C52262556600F739F1 /* BrightnessSlider.swift */,
|
||||
FC4387CC2262B82600F739F1 /* ChromaControlStylable.swift */,
|
||||
);
|
||||
path = Source;
|
||||
@ -181,8 +180,9 @@
|
||||
FC4387C722625C5F00F739F1 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FC4387C822625C7000F739F1 /* SliderTrackView.swift */,
|
||||
FCCA42A6226023F000BE2FF9 /* ChromaColorHandle.swift */,
|
||||
FC4387CA22625DA800F739F1 /* SliderHandleView.swift */,
|
||||
FC4387C822625C7000F739F1 /* SliderTrackView.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
@ -366,7 +366,7 @@
|
||||
FCEA4E272235AAA200C0A1B6 /* ChromaColorPicker.swift in Sources */,
|
||||
FC4387CD2262B82600F739F1 /* ChromaControlStylable.swift in Sources */,
|
||||
FCCA42AA2260329900BE2FF9 /* UIKit+DropShadow.swift in Sources */,
|
||||
FC4387C62262556600F739F1 /* BrightnessSlider.swift in Sources */,
|
||||
FC4387C62262556600F739F1 /* ChromaBrightnessSlider.swift in Sources */,
|
||||
FCCA42A7226023F000BE2FF9 /* ChromaColorHandle.swift in Sources */,
|
||||
FCCA42A5226022A800BE2FF9 /* ColorWheelView.swift in Sources */,
|
||||
FC4387C922625C7000F739F1 /* SliderTrackView.swift in Sources */,
|
||||
|
@ -13,83 +13,52 @@ class ViewController: UIViewController {
|
||||
@IBOutlet weak var colorDisplayView: UIView!
|
||||
|
||||
let colorPicker = ChromaColorPicker()
|
||||
|
||||
let temp = BrightnessSlider()
|
||||
|
||||
let brightnessSlider = ChromaBrightnessSlider()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
temp.frame = CGRect(x: 30, y: 70, width: 320, height: 32)
|
||||
view.addSubview(temp)
|
||||
|
||||
temp.trackColor = UIColor.red
|
||||
|
||||
|
||||
setupColorPicker()
|
||||
setupBrightnessSlider()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
print()
|
||||
}
|
||||
|
||||
private func setupColorPicker() {
|
||||
colorPicker.translatesAutoresizingMaskIntoConstraints = false
|
||||
colorPicker.showsBrightnessSlider = true
|
||||
view.addSubview(colorPicker)
|
||||
|
||||
let verticalOffset = -defaultColorPickerSize.height / 6
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
colorPicker.centerXAnchor.constraint(equalTo: view.centerXAnchor),
|
||||
colorPicker.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||
colorPicker.widthAnchor.constraint(equalToConstant: 400),
|
||||
colorPicker.heightAnchor.constraint(equalToConstant: 400)
|
||||
colorPicker.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: verticalOffset),
|
||||
colorPicker.widthAnchor.constraint(equalToConstant: defaultColorPickerSize.width),
|
||||
colorPicker.heightAnchor.constraint(equalToConstant: defaultColorPickerSize.height)
|
||||
])
|
||||
}
|
||||
|
||||
private func setupBrightnessSlider() {
|
||||
brightnessSlider.connect(to: colorPicker)
|
||||
|
||||
// Style
|
||||
brightnessSlider.trackColor = UIColor.red
|
||||
brightnessSlider.handle.borderWidth = 3.0 // Example of customizing the handle's properties.
|
||||
|
||||
// Layout
|
||||
brightnessSlider.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(brightnessSlider)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
brightnessSlider.centerXAnchor.constraint(equalTo: colorPicker.centerXAnchor),
|
||||
brightnessSlider.topAnchor.constraint(equalTo: colorPicker.bottomAnchor, constant: 28),
|
||||
brightnessSlider.widthAnchor.constraint(equalTo: colorPicker.widthAnchor, multiplier: 0.9),
|
||||
brightnessSlider.heightAnchor.constraint(equalTo: brightnessSlider.widthAnchor, multiplier: brightnessSliderWidthHeightRatio)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class ViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var colorDisplayView: UIView!
|
||||
var colorPicker: ChromaColorPicker!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
/* Calculate relative size and origin in bounds */
|
||||
let pickerSize = CGSize(width: view.bounds.width*0.8, height: view.bounds.width*0.8)
|
||||
let pickerOrigin = CGPoint(x: view.bounds.midX - pickerSize.width/2, y: view.bounds.midY - pickerSize.height/2)
|
||||
|
||||
/* Create Color Picker */
|
||||
colorPicker = ChromaColorPicker(frame: CGRect(origin: pickerOrigin, size: pickerSize))
|
||||
colorPicker.delegate = self
|
||||
|
||||
/* Customize the view (optional) */
|
||||
colorPicker.padding = 10
|
||||
colorPicker.stroke = 3 //stroke of the rainbow circle
|
||||
colorPicker.currentAngle = Float.pi
|
||||
|
||||
/* Customize for grayscale (optional) */
|
||||
colorPicker.supportsShadesOfGray = true // false by default
|
||||
//colorPicker.colorToggleButton.grayColorGradientLayer.colors = [UIColor.lightGray.cgColor, UIColor.gray.cgColor] // You can also override gradient colors
|
||||
|
||||
|
||||
colorPicker.hexLabel.textColor = UIColor.white
|
||||
|
||||
/* Don't want an element like the shade slider? Just hide it: */
|
||||
//colorPicker.shadeSlider.hidden = true
|
||||
|
||||
self.view.addSubview(colorPicker)
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewController: ChromaColorPickerDelegate {
|
||||
func colorPickerDidChooseColor(_ colorPicker: ChromaColorPicker, color: UIColor) {
|
||||
//Set color for the display view
|
||||
colorDisplayView.backgroundColor = color
|
||||
|
||||
//Perform zesty animation
|
||||
UIView.animate(withDuration: 0.2,
|
||||
animations: {
|
||||
self.colorDisplayView.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
|
||||
}, completion: { (done) in
|
||||
UIView.animate(withDuration: 0.2, animations: {
|
||||
self.colorDisplayView.transform = CGAffineTransform.identity
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
private let defaultColorPickerSize = CGSize(width: 320, height: 320)
|
||||
private let brightnessSliderWidthHeightRatio: CGFloat = 0.1
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// BrightnessSlider.swift
|
||||
// ChromaBrightnessSlider.swift
|
||||
// ChromaColorPicker
|
||||
//
|
||||
// Created by Jon Cardasis on 4/13/19.
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
public class ChromaBrightnessSlider: UIControl, ChromaControlStylable {
|
||||
|
||||
/// The value of the slider between [0.0, 1.0].
|
||||
public var currentValue: CGFloat = 0.0 {
|
||||
@ -22,9 +22,12 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
|
||||
/// The value of the color the handle is currently displaying.
|
||||
public var currentColor: UIColor {
|
||||
return sliderHandleView.handleColor
|
||||
return handle.handleColor
|
||||
}
|
||||
|
||||
/// The handle control of the slider.
|
||||
public let handle = SliderHandleView()
|
||||
|
||||
public var borderWidth: CGFloat = 4.0 {
|
||||
didSet { setNeedsLayout() }
|
||||
}
|
||||
@ -59,6 +62,13 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
updateShadowIfNeeded()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
/// Attaches control to the provided color picker.
|
||||
public func connect(to colorPicker: ChromaColorPicker) {
|
||||
colorPicker.connect(self)
|
||||
}
|
||||
|
||||
// MARK: - Control
|
||||
|
||||
public override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
|
||||
@ -89,7 +99,6 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
|
||||
// MARK: - Private
|
||||
internal let sliderTrackView = SliderTrackView()
|
||||
internal let sliderHandleView = SliderHandleView()
|
||||
|
||||
/// The amount of padding caused by visual stylings
|
||||
internal var horizontalPadding: CGFloat {
|
||||
@ -101,7 +110,7 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
}
|
||||
|
||||
internal var interactableBounds: CGRect {
|
||||
let horizontalOffset = -(sliderHandleView.bounds.width / 2) + horizontalPadding
|
||||
let horizontalOffset = -(handle.bounds.width / 2) + horizontalPadding
|
||||
return bounds.insetBy(dx: horizontalOffset, dy: 0)
|
||||
}
|
||||
|
||||
@ -125,12 +134,12 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
}
|
||||
|
||||
internal func setupSliderHandleView() {
|
||||
sliderHandleView.isUserInteractionEnabled = false
|
||||
addSubview(sliderHandleView)
|
||||
handle.isUserInteractionEnabled = false
|
||||
addSubview(handle)
|
||||
}
|
||||
|
||||
internal func updateShadowIfNeeded() {
|
||||
let views = [sliderHandleView, sliderTrackView]
|
||||
let views = [handle, sliderTrackView]
|
||||
|
||||
if showsShadow {
|
||||
let shadowProps = shadowProperties(forHeight: bounds.height)
|
||||
@ -150,7 +159,7 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
|
||||
CATransaction.begin()
|
||||
CATransaction.setDisableActions(true)
|
||||
sliderHandleView.handleColor = newColor
|
||||
handle.handleColor = newColor
|
||||
CATransaction.commit()
|
||||
|
||||
moveHandle(to: value)
|
||||
@ -177,6 +186,6 @@ public class BrightnessSlider: UIControl, ChromaControlStylable {
|
||||
let xPos = (clampedValue * confiningTrackFrame.width) + horizontalPadding
|
||||
let size = CGSize(width: bounds.height * 1.15, height: bounds.height)
|
||||
|
||||
sliderHandleView.frame = CGRect(origin: CGPoint(x: xPos - (size.width / 2), y: 0), size: size)
|
||||
handle.frame = CGRect(origin: CGPoint(x: xPos - (size.width / 2), y: 0), size: size)
|
||||
}
|
||||
}
|
@ -15,7 +15,6 @@ public protocol ChromaColorPickerDelegate {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@IBDesignable
|
||||
public class ChromaColorPicker: UIControl, ChromaControlStylable {
|
||||
|
||||
@ -27,14 +26,17 @@ public class ChromaColorPicker: UIControl, ChromaControlStylable {
|
||||
didSet { setNeedsLayout() }
|
||||
}
|
||||
|
||||
@IBInspectable public var showsBrightnessSlider: Bool = false {
|
||||
didSet { /* todo */ }
|
||||
}
|
||||
|
||||
@IBInspectable public var showsShadow: Bool = true {
|
||||
didSet { setNeedsLayout() }
|
||||
}
|
||||
|
||||
/// A brightness slider attached via the `connect(_:)` method.
|
||||
private(set) public weak var brightnessSlider: ChromaBrightnessSlider? {
|
||||
didSet {
|
||||
oldValue?.removeTarget(self, action: nil, for: .valueChanged)
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Initialization
|
||||
|
||||
override public init(frame: CGRect) {
|
||||
@ -53,10 +55,17 @@ public class ChromaColorPicker: UIControl, ChromaControlStylable {
|
||||
updateBorderIfNeeded()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
public func addHandle(at color: UIColor? = nil) -> ChromaColorHandle {
|
||||
return ChromaColorHandle(color: color ?? defaultHandleColorPosition)
|
||||
}
|
||||
|
||||
public func connect(_ slider: ChromaBrightnessSlider) {
|
||||
slider.addTarget(self, action: #selector(brightnessSliderDidValueChange(_:)), for: .valueChanged)
|
||||
brightnessSlider = slider
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
internal let colorWheelView = ColorWheelView()
|
||||
|
||||
@ -108,7 +117,10 @@ public class ChromaColorPicker: UIControl, ChromaControlStylable {
|
||||
print(pixelColor)
|
||||
}
|
||||
|
||||
|
||||
@objc
|
||||
internal func brightnessSliderDidValueChange(_ slider: ChromaBrightnessSlider) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal let defaultHandleColorPosition: UIColor = .black
|
||||
|
@ -8,31 +8,31 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
internal class SliderHandleView: UIView {
|
||||
public class SliderHandleView: UIView {
|
||||
|
||||
var handleColor: UIColor = .black {
|
||||
public var handleColor: UIColor = .black {
|
||||
didSet { updateHandleColor(to: handleColor) }
|
||||
}
|
||||
|
||||
var borderWidth: CGFloat = 3.0 {
|
||||
public var borderWidth: CGFloat = 3.0 {
|
||||
didSet { setNeedsLayout() }
|
||||
}
|
||||
|
||||
var borderColor: UIColor = .white {
|
||||
public var borderColor: UIColor = .white {
|
||||
didSet { setNeedsLayout() }
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
override public init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
override public func layoutSubviews() {
|
||||
let radius: CGFloat = bounds.height / 10
|
||||
handleLayer.path = makeRoundedTrianglePath(width: bounds.width, height: bounds.height, radius: radius)
|
||||
handleLayer.strokeColor = borderColor.cgColor
|
||||
@ -41,24 +41,24 @@ internal class SliderHandleView: UIView {
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
let handleLayer = CAShapeLayer()
|
||||
internal let handleLayer = CAShapeLayer()
|
||||
|
||||
private struct CornerPoint {
|
||||
internal struct CornerPoint {
|
||||
let center: CGPoint
|
||||
let startAngle: CGFloat
|
||||
let endAngle: CGFloat
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
internal func commonInit() {
|
||||
layer.addSublayer(handleLayer)
|
||||
updateHandleColor(to: handleColor)
|
||||
}
|
||||
|
||||
private func updateHandleColor(to color: UIColor) {
|
||||
internal func updateHandleColor(to color: UIColor) {
|
||||
handleLayer.fillColor = color.cgColor
|
||||
}
|
||||
|
||||
private func makeRoundedTrianglePath(width: CGFloat, height: CGFloat, radius: CGFloat) -> CGPath {
|
||||
internal func makeRoundedTrianglePath(width: CGFloat, height: CGFloat, radius: CGFloat) -> CGPath {
|
||||
let point1 = CGPoint(x: -width / 2, y: height / 2)
|
||||
let point2 = CGPoint(x: 0, y: -height / 2)
|
||||
let point3 = CGPoint(x: width / 2, y: height / 2)
|
||||
|
@ -10,8 +10,39 @@ import XCTest
|
||||
@testable import ChromaColorPicker
|
||||
|
||||
class ChromaColorPickerTests: XCTestCase {
|
||||
var subject: ChromaColorPicker!
|
||||
|
||||
func testDefault() {
|
||||
override func setUp() {
|
||||
subject = ChromaColorPicker(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
|
||||
}
|
||||
|
||||
func testTapGestureRecognizerIsAddedToColorWheelOnInitialization() {
|
||||
XCTAssertEqual(subject.colorWheelView.gestureRecognizers?.count, 1)
|
||||
}
|
||||
|
||||
func testConnectingSliderAddsEventTarget() {
|
||||
// Given
|
||||
let slider = ChromaBrightnessSlider(frame: .zero)
|
||||
|
||||
// When
|
||||
subject.connect(slider)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(subject.brightnessSlider, slider)
|
||||
XCTAssertEqual(slider.allTargets.first, subject)
|
||||
XCTAssertTrue(slider.allControlEvents.contains(.valueChanged))
|
||||
}
|
||||
|
||||
func testOldBrightnessSliderRemovesTargetWhenInstanceChanges() {
|
||||
// Given
|
||||
let slider1 = ChromaBrightnessSlider(frame: .zero)
|
||||
let slider2 = ChromaBrightnessSlider(frame: .zero)
|
||||
|
||||
// When
|
||||
subject.connect(slider1)
|
||||
subject.connect(slider2)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(slider1.allTargets.count, 0)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user