mirror of
https://github.com/joncardasis/ChromaColorPicker.git
synced 2024-11-22 06:32:06 +03:00
Resolved issue with handleSize. Added additional tests. Example homeHandle now changes tint based on lightness of selected color
This commit is contained in:
parent
7191d098d0
commit
8bf9b34f9b
@ -15,6 +15,8 @@
|
||||
35C376D61D5CF5300069D7A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D41D5CF5300069D7A1 /* Main.storyboard */; };
|
||||
35C376D81D5CF5300069D7A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D71D5CF5300069D7A1 /* Assets.xcassets */; };
|
||||
35C376DB1D5CF5300069D7A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D91D5CF5300069D7A1 /* LaunchScreen.storyboard */; };
|
||||
C83A935D23760C1600564E01 /* UIColor+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83A935C23760C1600564E01 /* UIColor+Utils.swift */; };
|
||||
C83A936023760C5900564E01 /* UIColor+UtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83A935E23760C3800564E01 /* UIColor+UtilsTests.swift */; };
|
||||
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 */; };
|
||||
@ -87,6 +89,8 @@
|
||||
35C376D71D5CF5300069D7A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
35C376DA1D5CF5300069D7A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
35C376DC1D5CF5300069D7A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C83A935C23760C1600564E01 /* UIColor+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Utils.swift"; sourceTree = "<group>"; };
|
||||
C83A935E23760C3800564E01 /* UIColor+UtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+UtilsTests.swift"; sourceTree = "<group>"; };
|
||||
FC1BD8BD2207D7B700817AF3 /* ChromaColorPickerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChromaColorPickerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaColorPickerTests.swift; sourceTree = "<group>"; };
|
||||
FC1BD8C12207D7B700817AF3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@ -215,6 +219,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FC4387DC226972EB00F739F1 /* UIColor+Brightness.swift */,
|
||||
C83A935C23760C1600564E01 /* UIColor+Utils.swift */,
|
||||
FCCA42A92260329900BE2FF9 /* UIView+DropShadow.swift */,
|
||||
FC89B7E32325C24F00D007AB /* UIView+Utils.swift */,
|
||||
);
|
||||
@ -225,6 +230,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FCE07BFD227B4A8100920217 /* UIColor+BrightnessTests.swift */,
|
||||
C83A935E23760C3800564E01 /* UIColor+UtilsTests.swift */,
|
||||
FCE07C03227B4DB900920217 /* UIView+DropShadowTests.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
@ -405,6 +411,7 @@
|
||||
FCCA42AA2260329900BE2FF9 /* UIView+DropShadow.swift in Sources */,
|
||||
FC4387DE226974FD00F739F1 /* UIColor+Brightness.swift in Sources */,
|
||||
FC4387C62262556600F739F1 /* ChromaBrightnessSlider.swift in Sources */,
|
||||
C83A935D23760C1600564E01 /* UIColor+Utils.swift in Sources */,
|
||||
FCCA42A7226023F000BE2FF9 /* ChromaColorHandle.swift in Sources */,
|
||||
FCCA42A5226022A800BE2FF9 /* ColorWheelView.swift in Sources */,
|
||||
FC4387C922625C7000F739F1 /* SliderTrackView.swift in Sources */,
|
||||
@ -426,6 +433,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
FCE07C06227B525000920217 /* ChromaControlStylableTests.swift in Sources */,
|
||||
C83A936023760C5900564E01 /* UIColor+UtilsTests.swift in Sources */,
|
||||
FC89B7E02325B07F00D007AB /* ChromaBrightnessSliderTests.swift in Sources */,
|
||||
FC89B7E22325B8B900D007AB /* FakeTouch.swift in Sources */,
|
||||
FCE07C0C228A0F7500920217 /* ChromaColorHandleTests.swift in Sources */,
|
||||
|
@ -22,6 +22,13 @@ class ViewController: UIViewController {
|
||||
setupColorPickerHandles()
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
private var homeHandle: ChromaColorHandle! // reference to home handle
|
||||
|
||||
private func setupColorPicker() {
|
||||
colorPicker.delegate = self
|
||||
colorPicker.translatesAutoresizingMaskIntoConstraints = false
|
||||
@ -57,14 +64,24 @@ class ViewController: UIViewController {
|
||||
}
|
||||
|
||||
private func setupColorPickerHandles() {
|
||||
// (Optional) Assign a custom handle size - all handles appear as the same size
|
||||
// colorPicker.handleSize = CGSize(width: 48, height: 60)
|
||||
|
||||
// 1. Add handle and then customize
|
||||
addHomeHandle()
|
||||
|
||||
// 2. Add a handle via a color
|
||||
let peachColor = UIColor(red: 1, green: 203 / 255, blue: 164 / 255, alpha: 1)
|
||||
colorPicker.addHandle(at: peachColor)
|
||||
|
||||
// 3. Create a custom handle and add to picker
|
||||
let customHandle = ChromaColorHandle()
|
||||
customHandle.color = UIColor.purple
|
||||
colorPicker.addHandle(customHandle)
|
||||
}
|
||||
|
||||
private func addHomeHandle() {
|
||||
let homeHandle = colorPicker.addHandle(at: .blue)
|
||||
homeHandle = colorPicker.addHandle(at: .blue)
|
||||
|
||||
// Setup custom handle view with insets
|
||||
let customImageView = UIImageView(image: #imageLiteral(resourceName: "home").withRenderingMode(.alwaysTemplate))
|
||||
@ -78,8 +95,18 @@ class ViewController: UIViewController {
|
||||
extension ViewController: ChromaColorPickerDelegate {
|
||||
func colorPickerHandleDidChange(_ colorPicker: ChromaColorPicker, handle: ChromaColorHandle, to color: UIColor) {
|
||||
colorDisplayView.backgroundColor = color
|
||||
|
||||
// Here I can detect when the color is too bright to show a white icon
|
||||
// on the handle and change its tintColor.
|
||||
if handle === homeHandle, let imageView = homeHandle.accessoryView as? UIImageView {
|
||||
let colorIsBright = color.isLight
|
||||
print(color.lightness)
|
||||
|
||||
UIView.animate(withDuration: 0.2, animations: {
|
||||
imageView.tintColor = colorIsBright ? .black : .white
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// ChromaColorPicker2.swift
|
||||
// ChromaColorPicker.swift
|
||||
// ChromaColorPicker
|
||||
//
|
||||
// Created by Jon Cardasis on 3/10/19.
|
||||
@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Accelerate
|
||||
|
||||
public protocol ChromaColorPickerDelegate: class {
|
||||
/// When a handle's value has changed.
|
||||
@ -41,7 +40,7 @@ public class ChromaColorPicker: UIControl, ChromaControlStylable {
|
||||
|
||||
/// The size handles should be displayed at.
|
||||
public var handleSize: CGSize = defaultHandleSize {
|
||||
didSet { layoutNow() }
|
||||
didSet { setNeedsLayout() }
|
||||
}
|
||||
|
||||
/// An extension to handles' hitboxes in the +Y direction.
|
||||
|
28
Source/Extensions/UIColor+Utils.swift
Normal file
28
Source/Extensions/UIColor+Utils.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// UIColor+Utils.swift
|
||||
// ChromaColorPicker
|
||||
//
|
||||
// Created by Jonathan Cardasis on 11/8/19.
|
||||
// Copyright © 2019 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public extension UIColor {
|
||||
|
||||
/// The value of lightness a color has. Value between [0.0, 1.0]
|
||||
/// Based on YIQ color space for constrast (https://www.w3.org/WAI/ER/WD-AERT/#color-contrast)
|
||||
var lightness: CGFloat {
|
||||
var red: CGFloat = 0
|
||||
var green: CGFloat = 0
|
||||
var blue: CGFloat = 0
|
||||
getRed(&red, green: &green, blue: &blue, alpha: nil)
|
||||
|
||||
return ((red * 299) + (green * 587) + (blue * 114)) / 1000
|
||||
}
|
||||
|
||||
/// Whether or not the color is considered 'light' in terms of contrast.
|
||||
var isLight: Bool {
|
||||
return lightness >= 0.5
|
||||
}
|
||||
}
|
@ -190,6 +190,49 @@ class ChromaColorPickerTests: XCTestCase {
|
||||
// Then
|
||||
XCTAssertTrue(eventDidTrigger)
|
||||
}
|
||||
|
||||
func testHitTestShouldReturnSelfWhenTouchIsWithinSelf() {
|
||||
subject.colorWheelView.layoutIfNeeded()
|
||||
|
||||
// Given
|
||||
let touchLocation = subject.center
|
||||
|
||||
// When
|
||||
let hitView = subject.hitTest(touchLocation, with: UIEvent())
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(hitView, subject)
|
||||
}
|
||||
|
||||
func testHitTestShouldReturnSelfWhenTouchIsWithinSelfPlusHandleRadius() {
|
||||
subject.colorWheelView.layoutIfNeeded()
|
||||
|
||||
// Given
|
||||
let touchLocation = CGPoint(x: -subject.handleSize.width / 2.0, y: subject.center.y)
|
||||
|
||||
// When
|
||||
let hitView = subject.hitTest(touchLocation, with: UIEvent())
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(hitView, subject)
|
||||
}
|
||||
|
||||
func testHitTestShouldReturnNilWhenTouchIsOutsideHitbox() {
|
||||
subject.colorWheelView.layoutIfNeeded()
|
||||
|
||||
// Given
|
||||
let extendedSize: CGFloat = 12
|
||||
subject.handleSize = CGSize(width: extendedSize, height: extendedSize)
|
||||
let fakeHandle = makeFakeHandle()
|
||||
let touchLocation = CGPoint(x: -extendedSize - 1, y: subject.center.y)
|
||||
setCurrentHandle(to: fakeHandle)
|
||||
|
||||
// When
|
||||
let hitView = subject.hitTest(touchLocation, with: UIEvent())
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(hitView, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
61
Tests/Extensions/UIColor+UtilsTests.swift
Normal file
61
Tests/Extensions/UIColor+UtilsTests.swift
Normal file
@ -0,0 +1,61 @@
|
||||
//
|
||||
// UIColor+UtilsTests.swift
|
||||
// ChromaColorPicker
|
||||
//
|
||||
// Created by Jonathan Cardasis on 11/8/19.
|
||||
// Copyright © 2019 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import ChromaColorPicker
|
||||
|
||||
class UIColor_UtilsTests: XCTestCase {
|
||||
|
||||
func testLightnessReturns1ForWhite() {
|
||||
XCTAssertEqual(UIColor.white.lightness, 1.0, accuracy: 0.001)
|
||||
}
|
||||
|
||||
func testLightnessReturns0ForBlack() {
|
||||
XCTAssertEqual(UIColor.black.lightness, 0.0, accuracy: 0.001)
|
||||
}
|
||||
|
||||
func testLightnessReturnsCorrectLightnessForYellow() {
|
||||
XCTAssertEqual(UIColor.yellow.lightness, 0.886, accuracy: 0.001)
|
||||
}
|
||||
|
||||
func testLightnessReturnsCorrectLightnessForBlue() {
|
||||
XCTAssertEqual(UIColor.blue.lightness, 0.114, accuracy: 0.001)
|
||||
}
|
||||
|
||||
func testBlueIsNotLight() {
|
||||
XCTAssertFalse(UIColor.blue.isLight)
|
||||
}
|
||||
|
||||
func testRedIsNotLight() {
|
||||
XCTAssertFalse(UIColor.red.isLight)
|
||||
}
|
||||
|
||||
func testPurpleIsNotLight() {
|
||||
XCTAssertFalse(UIColor.purple.isLight)
|
||||
}
|
||||
|
||||
func tesBlackIsNotLight() {
|
||||
XCTAssertFalse(UIColor.black.isLight)
|
||||
}
|
||||
|
||||
func testWhiteIsLight() {
|
||||
XCTAssertTrue(UIColor.white.isLight)
|
||||
}
|
||||
|
||||
func testGreenIsLight() {
|
||||
XCTAssertTrue(UIColor.green.isLight)
|
||||
}
|
||||
|
||||
func testOrangeIsLight() {
|
||||
XCTAssertTrue(UIColor.orange.isLight)
|
||||
}
|
||||
|
||||
func testYellowIsLight() {
|
||||
XCTAssertTrue(UIColor.yellow.isLight)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user