I like to present a different approach for the integration of a color panel. I wanted to have a color picker, and so I searched in the community and found one here (http://theappspace.com/custom-color-picker-in-swift/). I had to convert from swift 2 to 3. The final application was done in Xcode beta 9.5 starting from the silver Touchtracker.
I created a swift file with the ColorPicker class. There is also a protocol, which contains a method, which we will use in the DrawView. We will change the ColorPicker script later. Now open the storyboard and place a view and two buttons (SELECT and CANCEL button). Adjust the size of the view to your needs like width of 320 and height of 100 and set the custom class in the identity inspector to ColorPicker. Place the two buttons into a horizontal stackview with “fill proportionally”. Then place the stackview and the view into a new vertical stackview with the buttons on top. In the attributes inspector set fill proportionally and spacing to 10. Place the stackview manually close to the top and center it. Then open new constraints for the ColorPicker view and set the height to 100. Now open new constraints for the main stackview and click on the top, right and left constraints. Don’t change the total value of right and left. If right is 10 and left is 8, set both to 9. Add 3 constraints. Make this stackview hidden in the attributes inspector.
Now the scripts need to be adjusted. First open the ColorPicker class and delete the touchesBegan, Moved and Ended functions, because the same functions are overridden in the DrawView class. Then change the updateColor function. We have to call this function now from the DrawView class.
func updateColor(_ curSelectionX: CGFloat){
selectedColor = UIColor(hue: (curSelectionX / self.frame.size.width), saturation: 1.0, brightness: 1.0, alpha: 1.0)
self.delegate.pickedColor!(selectedColor)
self.setNeedsDisplay()
}
Now change Line,swift and add
var lineColor: UIColor = UIColor.black
Now open DrawView.swift. Change the class to add colorDelegate, which allows us to get the color from the picker.
class DrawView: UIView, colorDelegate, UIGestureRecognizerDelegate {
Add variables for the storyboard objects and connect the main stackview with “holdViews”, the colorPicker view and the two buttons. The other variables we need later.
// Objects from the storyboard connected
@IBOutlet var holdViews: UIStackView!
@IBOutlet var colorPicker: ColorPicker!
@IBOutlet var colorView: UIButton!
@IBOutlet var cancelNewColor: UIButton!
// Var to hold the color from the colorpicker
var selectedColor: UIColor = UIColor.black
var curSelectionYmin: Int = 0
var curSelectionYmax: Int = 0
Make longPressRecognizer accessible to the whole class.
`var longPressRecognizer: UILongPressGestureRecognizer!`
Add the swipe up script.
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(DrawView.swipeup(gesture:)))
swipeUp.direction = .up
// See my comment at the bottom.
swipeUp.numberOfTouchesRequired = 2
addGestureRecognizer(swipeUp)
Then add this function for the swipe up gesture. I added @objc to all button type functions, which is required in swift 4.
@objc func swipeup(gesture: UISwipeGestureRecognizer) -> Void {
if gesture.direction == UISwipeGestureRecognizerDirection.up {
print("Swipe Up")
currentLines.removeAll()
colorPicker.delegate = self;
colorView.setTitle("SELECT", for: .normal)
colorView.backgroundColor = selectedColor
colorView.addTarget(self, action: #selector(setColor(_:)), for: UIControlEvents.touchUpInside)
cancelNewColor.setTitle("CANCEL", for: .normal)
cancelNewColor.addTarget(self, action: #selector(setColor(_:)), for: UIControlEvents.touchUpInside)
// Define the y coordinates for the colorpicker
curSelectionYmin = Int(colorPicker.frame.minY + 10 + colorView.frame.height)
curSelectionYmax = Int(colorPicker.frame.maxY + 10 + colorView.frame.height)
// Making the colorpicker visible
holdViews.isHidden = false
// Get color by a long press
moveRecognizer.isEnabled = false
longPressRecognizer.isEnabled = false
}
}
Add the next two functions. “pickedColor” connects to the ColorPicker class.
func pickedColor(_ color: UIColor) {
// Setting the color
colorView.backgroundColor = color;
}
@objc func setColor(_ sender: UIButton) {
print("Color selected")
// Change color only with SELECT button
if sender.currentTitle == "SELECT" {
selectedColor = colorView.backgroundColor!
}
holdViews.isHidden = true
// Restore original gestures
longPressRecognizer.isEnabled = true
moveRecognizer.isEnabled = true
}
Change the stroke function.
func stroke(_ Line: Line, color: UIColor = .black) {
Change inside the function.
// When change color of moving lines or currentLines
if color != .black {
color.setStroke()
} else {
Line.lineColor.setStroke()
}
Change draw.
override func draw(_ rect: CGRect) {
// Draw finished lines
for line in finishedLines {
stroke(line)
}
// Draw current lines
for (_, line) in currentLines {
stroke(line, color: .red)
}
if let index = selectedLineIndex {
let selectedLine = finishedLines[index]
stroke(selectedLine, color: .green)
}
}
Add this to all touches classes.
let touch = touches.first
if holdViews.isHidden == false {
let coltouch = Int((touch?.location(in: self).y)!)
if coltouch <= curSelectionYmax && coltouch >= curSelectionYmin {
let curSelectionX = ((touch?.location(in: self).x)! - holdViews.frame.minX)
colorPicker.updateColor(curSelectionX)
}
} else {
for touch in touches {
Change the newline to this in touchesBegan.
let newLine = Line(begin: location, end: location, lineColor: selectedColor)
When you test the app now you will see the color picker. Press a bit longer and release on a color for the colorView to change. To be honest I never got any three finger swipe to work on the simulator even after activating the three finger drag for the trackpad. So I tested everything with two fingers (option + shift).