TakeScoop / SwiftyButton

Simple and customizable button in Swift
MIT License
553 stars 43 forks source link

Define Pressable Button colors via XIB/Storyboards #7

Open gearoidoceallaigh opened 7 years ago

gearoidoceallaigh commented 7 years ago

I'm able to change the colours on a FlatButton but not a PressableButton via Storyboards.

Is there a way to do this without dropping into the code?

Great library, thanks :)

ldiqual commented 7 years ago

@gearoidoceallaigh Thanks for opening an issue! At the moment there is no way to do this. My thinking when using ColorSet was that the button + shadow colors should only be defined together. Having two separate properties increases the risk of forgetting to set one after setting another. For instance:

button.colors = .init(button: .cyan, shadow: .blue)
button.disabledColors = .init(button: .grey, shadow: .black)

as opposed to

button.buttonColor = .cyan
button.shadowColor = .blue
button.disabledButtonColor = .grey
button.disabledShadowColor = .black

where you could forget to set any of these.

The drawback, as you mentioned, is that ColorSet cannot be defined from the storyboard. I'll think a bit more about this to see if I can find an acceptable workaround. In the meantime, if someone is interested in this feature, please upvote the original post. Thank you!

aal89 commented 6 years ago

I too ran into this problem and 'fixed' it like this:

Swift 4 ahead. I hope this is helpful for someone. After you copy paste this into your project, you now also have a buttonColor inspectable in your IB for PressableButton. I might open a PR with a proper implementation, if there's enough interest.

extension PressableButton {

    @IBInspectable
    var buttonColor: UIColor {
        get {
            // The ColorSet has it's properties set to internal. So the get() is
            // improperly implemented, we cannot get the current value (yet?).
            // As a result this is a hack in which we retrieve the pixel color
            // of the background UIImage.

            // We use the cornerRadius as an offset else we might read an
            // unintended pixel.
            let imageTopPoint = CGPoint(x: self.cornerRadius, y: self.cornerRadius)
            return self.currentBackgroundImage?.getPixelColor(pos: imageTopPoint) ?? UIColor.black
        }
        set {
            self.colors = ColorSet(button: newValue, shadow: newValue.darker(by: 15.0) ?? newValue)
        }
    }

}

extension UIImage {

    func getPixelColor(pos: CGPoint) -> UIColor {

        let pixelData = self.cgImage!.dataProvider!.data
        let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

        let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4

        let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
        let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
        let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
        let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)

        return UIColor(red: r, green: g, blue: b, alpha: a)
    }

}

extension UIColor {

    func lighter(by percentage: CGFloat = 30.0) -> UIColor? {
        return self.adjust(by: abs(percentage))
    }

    func darker(by percentage: CGFloat = 30.0) -> UIColor? {
        return self.adjust(by: -1 * abs(percentage))
    }

    func adjust(by percentage: CGFloat = 30.0) -> UIColor? {
        var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0;
        if(self.getRed(&r, green: &g, blue: &b, alpha: &a)) {
            return UIColor(red: min(r + percentage / 100, 1.0),
                           green: min(g + percentage / 100, 1.0),
                           blue: min(b + percentage / 100, 1.0),
                           alpha: a)
        } else {
            return nil
        }
    }

}