uibutton uibutton - Come posso fare in modo che un pulsante abbia un bordo arrotondato in Swift?




programmatically ios (10)

È possibile utilizzare questa sottoclasse di UIButton per personalizzare UIButton in base alle proprie esigenze.

visita questo repository Github come riferimento

class RoundedRectButton: UIButton {

    var selectedState: Bool = false

    override func awakeFromNib() {
        super.awakeFromNib()
        layer.borderWidth = 2 / UIScreen.main.nativeScale
        layer.borderColor = UIColor.white.cgColor
        contentEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    }


    override func layoutSubviews(){
        super.layoutSubviews()
        layer.cornerRadius = frame.height / 2
        backgroundColor = selectedState ? UIColor.white : UIColor.clear
        self.titleLabel?.textColor = selectedState ? UIColor.green : UIColor.white
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        selectedState = !selectedState
        self.layoutSubviews()
    }
}

Sto costruendo un'app usando swift nell'ultima versione di Xcode 6 e vorrei sapere come posso modificare il mio pulsante in modo che possa avere un bordo arrotondato che potrei aggiustare io stesso se necessario. Una volta fatto, come posso cambiare il colore del bordo stesso senza aggiungere uno sfondo ad esso? In altre parole, voglio un pulsante leggermente arrotondato senza sfondo, solo un bordo di 1 pixel di un determinato colore.


Penso che il modo più semplice e più pulito, è quello di utilizzare il protocollo per evitare l'ereditarietà e la ripetizione del codice. Puoi modificare queste proprietà direttamente dallo storyboard

protocol Traceable {
    var cornerRadius: CGFloat { get set }
    var borderColor: UIColor? { get set }
    var borderWidth: CGFloat { get set }
}

extension UIView: Traceable {

    @IBInspectable var cornerRadius: CGFloat {
        get { return layer.cornerRadius }
        set {
            layer.masksToBounds = true
            layer.cornerRadius = newValue
        }
    }

    @IBInspectable var borderColor: UIColor? {
        get {
            guard let cgColor = layer.borderColor else { return nil }
            return  UIColor(cgColor: cgColor)
        }
        set { layer.borderColor = newValue?.cgColor }
    }

    @IBInspectable var borderWidth: CGFloat {
        get { return layer.borderWidth }
        set { layer.borderWidth = newValue }
    }
}

Aggiornare

In questo link puoi trovare un esempio con l'utilità del protocollo Tracciabile


@IBOutlet weak var button: UIButton!

...

Penso che per il raggio basta questo parametro:

button.layer.cornerRadius = 5

come suggerimento a parte assicurati che il tuo pulsante non sia sottoclasse di alcuna classe personalizzata in story board, in tal caso il tuo codice posto migliore dovrebbe essere in classe personalizzata, il codice di auto-elaborazione funziona solo fuori dalla classe personalizzata se il tuo pulsante è sottoclasse di default La classe e il punto vendita di UIButton, spero che questo possa aiutare qualcuno a chiedersi come mai le radio corner non si applicano al mio pulsante dal codice.


Questa classe si basa su tutti i commenti e i suggerimenti delle risposte e può anche essere progettata direttamente da xcode. Copia nel tuo progetto e inserisci un UIButton e modifica l'uso della classe personalizzata, ora seleziona il bordo o il colore di sfondo da xcode per gli stati normali e / o evidenziati.

//
//  RoundedButton.swift
//

import UIKit

@IBDesignable
class RoundedButton:UIButton {

    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    //Normal state bg and border
    @IBInspectable var normalBorderColor: UIColor? {
        didSet {
            layer.borderColor = normalBorderColor?.CGColor
        }
    }

    @IBInspectable var normalBackgroundColor: UIColor? {
        didSet {
            setBgColorForState(normalBackgroundColor, forState: .Normal)
        }
    }


    //Highlighted state bg and border
    @IBInspectable var highlightedBorderColor: UIColor?

    @IBInspectable var highlightedBackgroundColor: UIColor? {
        didSet {
            setBgColorForState(highlightedBackgroundColor, forState: .Highlighted)
        }
    }


    private func setBgColorForState(color: UIColor?, forState: UIControlState){
        if color != nil {
            setBackgroundImage(UIImage.imageWithColor(color!), forState: forState)

        } else {
            setBackgroundImage(nil, forState: forState)
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        layer.cornerRadius = layer.frame.height / 2
        clipsToBounds = true

        if borderWidth > 0 {
            if state == .Normal && !CGColorEqualToColor(layer.borderColor, normalBorderColor?.CGColor) {
                layer.borderColor = normalBorderColor?.CGColor
            } else if state == .Highlighted && highlightedBorderColor != nil{
                layer.borderColor = highlightedBorderColor!.CGColor
            }
        }
    }

}

//Extension Required by RoundedButton to create UIImage from UIColor
extension UIImage {
    class func imageWithColor(color: UIColor) -> UIImage {
        let rect: CGRect = CGRectMake(0, 0, 1, 1)
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, 1), false, 1.0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Per fare questo lavoro nello storyboard (Interface Builder Inspector)

Con l'aiuto di IBDesignable , possiamo aggiungere ulteriori opzioni a Interface Builder Inspector per UIButton e modificarle sullo storyboard. Innanzitutto, aggiungi il seguente codice al tuo progetto.

@IBDesignable extension UIButton {

    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
        }
        get {
            return layer.cornerRadius
        }
    }

    @IBInspectable var borderColor: UIColor? {
        set {
            guard let uiColor = newValue else { return }
            layer.borderColor = uiColor.cgColor
        }
        get {
            guard let color = layer.borderColor else { return nil }
            return UIColor(cgColor: color)
        }
    }
}

Quindi imposta semplicemente gli attributi per i pulsanti sullo storyboard.


Ho creato un sottolivello UIButton semplice che utilizza tintColor per i colori del bordo e del testo e, quando evidenziato, cambia lo sfondo in tintColor .

class BorderedButton: UIButton {

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    layer.borderWidth = 1.0
    layer.borderColor = tintColor.CGColor
    layer.cornerRadius = 5.0
    clipsToBounds = true
    contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
    setTitleColor(tintColor, forState: .Normal)
    setTitleColor(UIColor.whiteColor(), forState: .Highlighted)
    setBackgroundImage(UIImage(color: tintColor), forState: .Highlighted)
}
}

Questo fa uso di un'estensione UIImage che crea un'immagine da un colore, ho trovato quel codice qui: https://.com/a/33675160

Funziona meglio quando è impostato per digitare Custom nel generatore di interfacce poiché il tipo di sistema predefinito modifica leggermente i colori quando il pulsante è evidenziato.


Sulla base della risposta @returntrue sono riuscito a implementarlo in Interface Builder.

Per ottenere il pulsante degli angoli arrotondati usando Interface Builder aggiungi un Key Path = "layer.cornerRadius" con Type = "Number" e Value = "10" (o altro valore come richiesto) User Defined RunTime Attribute " Identity Inspector di il tasto.


Usa button.layer.cornerRadius , button.layer.borderColor e button.layer.borderWidth . Nota che borderColor richiede un CGColor , quindi potresti dire (Swift 3/4):

button.backgroundColor = .clear
button.layer.cornerRadius = 5
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor

La seguente funzione è utilizzata in qualsiasi vista.

extension UIView {
    func shake() {
        let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.duration = 0.6
        animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
        layer.add(animation, forKey: "shake")
    }
}




swift uibutton