IBDesignable 사용한 커스텀 버튼, 스토리보드에서 설정하면 디자인이 바로 적용되는 것을 볼 수 있음.

- 모서리 Radius 

- 이미지 + 텍스트 정렬 ( 가로배치 / 세로배치)

- 줄간격

- 자간

- Gradient Border / Background 컬러 적용

 

* 주의사항

- 소스에 폰트관련 내용은 커스텀 폰트 사용으로 소스를 첨부하지 않았다. 변경해서 사용할것

https://limdongo.tistory.com/25 게시물의 UIViewExension 소스를 첨부하면 됨.

 

import UIKit


enum ImageFixedAlignedType: Int {
    case NONE = 0
    case CENTER_IMAGE_TEXT
    case CENTER_TEXT_IMAGE
    case EDGE_TEXT_IMAGE
}
@IBDesignable class IBCusomButton: UIButton {
    
    
    @IBInspectable
    public var fontStyleNumber: Int = 2{
        didSet {
            setup()
        }
    }
    
    @IBInspectable
    public var fontsize: CGFloat = 12.0 {
        didSet {
            setup()
        }
    }
    
    // 줄간격 default : 21
    @IBInspectable open var linesspacing:CGFloat = -1.0 {
        didSet {
            updateWithSpacing()
        }
    }
    
    @IBInspectable open var letterSpacing:CGFloat = 1.0 {
        didSet {
            updateWithSpacing()
        }

    }
    /*
    @IBInspectable
    public var fontColor: UIColor = UIColor.barbiePink {
        didSet {
            setup()
        }
    }
 */
    
    @IBInspectable
    public var alignTextSpacing: CGFloat = 0.0 {
        didSet {
           
            setup()
        }
    }
    
    /// 이미지 + 텍스트 정렬 방식
    @IBInspectable public var imagefixedInset: Int = 0{
        didSet {
            
            setup()
           
        }
    }
    
    @IBInspectable
    public var iconTintColor: UIColor = .black {
        didSet {
            setup()
        }
    }
    
    /// 버튼  Radius 무조건 둥글게 (폰 해상도 반영 )
    @IBInspectable
    public var halfCornerRadius: Bool = false{
        didSet {
            
            if halfCornerRadius == true {
                cornerRadius  = self.frame.size.height/2.0
                setup()
            }
        }
    }
    
//    var cornerRadius: CGFloat = 0.0    /// halfCornerRadius FALSE 일경우 적용
    @IBInspectable
    public var cornerRadius: CGFloat = 0.0{
        didSet {
            if halfCornerRadius == false {
                setup()
            }
        }
    }
    
    @IBInspectable
    public var borderWidth: CGFloat = 0.0{
        didSet {
            setup()
        }
    }
    
    @IBInspectable
    public var borderColor: UIColor = UIColor.clear {
        didSet {
            setup()
        }
    }
    
    @IBInspectable
    public var isGradientUseHighlight: Bool = false {
        didSet {
//            setup()
        }
    }

    @IBInspectable
    public var isGradientBorder: Bool = false {
        didSet {
            if isGradientBorder == false {
                self.borderColor(width: borderWidth, borderColor: borderColor)
                self.layer.cornerRadius = self.cornerRadius
            } else {
                setup()
            }
        }
    }
    
    @IBInspectable
    public var isGradientBackground: Bool = false{
        didSet {
            setup()
        }
    }
    
    @IBInspectable
    public var bgOpacity: CGFloat = 1.0{
        didSet {
            setup()
        }
    }
    
    var gradientStartPoint: CGPoint = CGPoint(x: 0.0, y: 0.0)
    var gradientEndPoint: CGPoint = CGPoint(x: 1, y: 0)
    
    var gradientBorderColors: [UIColor] = [UIColor.pinkishRed,
                                           UIColor.barbiePink,
                                           UIColor.marigold] {
        didSet {
            setup()
        }
    }
    
    //[UIColor.reddishPink.cgColor, UIColor.mango.cgColor]
    var gradientBGColors: [UIColor] = [UIColor.reddishPink, UIColor.mango] {
        didSet {
            setup()
        }
    }
    
    var gradientHightlightedColors: [UIColor] = [UIColor.pinkishGrey,UIColor.brownishGreyTwo] {
        didSet {
            setup()
        }
    }
    
    
    // 스토리보드에서 호출할 초기화 메서드
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    
    // 프로그래밍 방식으로 호출할 초기화 메서드
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    /*
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    */
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setup()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        if self.frame.width == 0 || self.frame.height == 0 {
            return
        }
        setup()
    }
    
    override var isHighlighted: Bool {
        get {
//            print(">>>> isHighlighted Get ")
            return super.isHighlighted
        } set {
            
            if isGradientUseHighlight {
                print(">>>> isHighlighted Set ")
                setup()
            }
            super.isHighlighted = newValue
        }
    }
    
    func setup() {
//        setupImageRightfixedAligned()
        /*
        if let imageInsetType = ImageFixedAlignedType(rawValue: imagefixedInset) {
            switch imageInsetType {
            case .CENTER_IMAGE_TEXT, .CENTER_TEXT_IMAGE:
                setupImagefixedCenterInset(aligned: imageInsetType)
            case .EDGE_TEXT_IMAGE:
                setupImageRightfixedAligned()
            default: break
            }
        }*/
        
        
        if imagefixedInset == ImageFixedAlignedType.CENTER_IMAGE_TEXT.rawValue {
            setupImagefixedCenterInset(aligned: ImageFixedAlignedType.CENTER_IMAGE_TEXT)
        } else if imagefixedInset == ImageFixedAlignedType.CENTER_TEXT_IMAGE.rawValue {
            setupImagefixedCenterInset(aligned: ImageFixedAlignedType.CENTER_TEXT_IMAGE)
        } else if imagefixedInset == ImageFixedAlignedType.EDGE_TEXT_IMAGE.rawValue {
            setupImageRightfixedAligned()
        }
        
        if self.isGradientBorder == true {
            self.removeLayer(layername: UIView.kLayerNameGradientBorder)
            self.addBorderGradient(width: self.borderWidth,
            colors: gradientBorderColors,
            cornerRadius: self.cornerRadius)
        } else {
            self.borderColor(width: self.borderWidth, borderColor: self.borderColor)
        }
        
        if self.isGradientBackground == true {
            self.removeLayer(layername: UIView.kLayerNameGradientBackground)
            
            if isHighlighted == false || isGradientUseHighlight == false {
                self.addBgGradient(colors: gradientBGColors, cornerRadius: self.cornerRadius,  opacity: bgOpacity, shadow: false, startPoint: gradientStartPoint, endPoint: gradientEndPoint)
            } else {
                self.addBgGradient(colors: gradientHightlightedColors, cornerRadius: self.cornerRadius, opacity: bgOpacity, shadow: false, startPoint: gradientStartPoint, endPoint: gradientEndPoint)
            }
        } else {
            self.removeLayer(layername: UIView.kLayerNameGradientBackground)
            
            if let bgColor = self.backgroundColor {
                self.backgroundColor = bgColor.withAlphaComponent(bgOpacity)
            }
        }
         
        if let fontStyle = FontStyleNumber.init(rawValue: fontStyleNumber) {
            
            let sytlefont = UIFont.notoSansFont(forFont: fontStyle.fontName, size: fontsize)
            
            self.titleLabel?.font = sytlefont
//            self.setTitleColor(self.fontColor, for: .normal)
//            self.titleLabel?.textAlignment = .center
            
            self.titleLabel?.adjustsFontForContentSizeCategory = true
//            self.titleLabel?.adjustsFontSizeToFitWidth = true
        }
        
        if alignTextSpacing > 0.0, self.isHidden == false {
            alignTextBelow(spacing: alignTextSpacing)
        }
        
        if self.imageView != nil {
            if let imageView = self.imageView, let image = imageView.image   {
                if self.iconTintColor != UIColor.black {
                    self.imageView?.image = image.withRenderingMode(.alwaysTemplate)
                    self.tintColor = iconTintColor
                }
            }
        }
        
        //self.clipsToBounds = true
        //autoresizingMask = [.flexibleWidth, .flexibleHeight]
        //contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.center
        //content 사이즈 변경 사항이 있을 경우 호출(다른 레이아웃 사이즈 조정??)
        invalidateIntrinsicContentSize()
    }
    
    /*
     - titleText Left and image Right Aligned
        속성 : 버튼 기본 설정 상태
        | title            😄 |
     */
    func setupImageRightfixedAligned() {
        
        self.semanticContentAttribute = .unspecified
//        self.contentHorizontalAlignment = .left
        
        self.imageEdgeInsets = UIEdgeInsets(top: 5, left: (bounds.width - 25), bottom: 5, right: 5)
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: (imageView?.frame.width)!)//+15)
    }
    
    /*  버튼 이미지, 텍스트 중앙 정렬
     - image Left and titleText Right Center Aligned
       속성 : semanticContentAttribute = .unspecified
     |       😄      korea        |
     |       😄       usa         |
     |       😄      japan        |
     
     
     - titleText Left and image Right Center Aligned
       속성 : semanticContentAttribute = .forceRightToLeft
     |        korea      😄       |
     |         usa       😄       |
     |        japan      😄       |
    */
    func setupImagefixedCenterInset(aligned type: ImageFixedAlignedType) {
        guard let title = self.titleLabel else { return }
        title.sizeToFit()
        
        let viewWidth = self.frame.width / 2.0
        var imageWidth = self.imageView?.frame.width ?? 0.0
        if imageWidth > 0.0 {
            imageWidth = imageWidth / 2.0
        }
        
        let titleWidth = title.frame.width / 2.0
        
        switch type {
        case .CENTER_TEXT_IMAGE:
            self.semanticContentAttribute = .forceRightToLeft
            self.contentHorizontalAlignment = .right
            self.titleEdgeInsets.right = viewWidth - titleWidth - imageWidth
            self.imageEdgeInsets.right = (viewWidth/2.0) - imageWidth
        case .CENTER_IMAGE_TEXT:
            self.semanticContentAttribute = .unspecified
            self.contentHorizontalAlignment = .left
            self.titleEdgeInsets.left = viewWidth - titleWidth - imageWidth
            self.imageEdgeInsets.left = (viewWidth/2.0) - imageWidth
        default: break
        }
    }
    
    /*
     이미지(상단) / 텍스트(하단) 배치
    */
    func alignTextBelow(spacing: CGFloat) {
        
        //let spacing: CGFloat = 6.0
        if self.imageView != nil {
            if let imageView = self.imageView   {
                
                let imageSize = imageView.frame.size
                self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0)
                let titleSize = self.titleLabel!.frame.size                
                self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0, bottom: 0, right: -titleSize.width)
            }
        }
    }

    func updateWithSpacing() {
        guard let lable = self.titleLabel, let attributedText = lable.attributedText else {
            return
        }
        
        let attributedString = NSMutableAttributedString(string: lable.text ?? "")// : NSMutableAttributedString(attributedString: lable.attributedText ?? "")
        
        // 자간 간격 설정
        attributedString.addAttribute(NSAttributedString.Key.kern, value: self.letterSpacing, range: NSRange(location: 0, length: attributedString.length))
        
        // 줄간격 (default -  21)
        if linesspacing > 0 {
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.minimumLineHeight = linesspacing
            paragraphStyle.maximumLineHeight = linesspacing
            paragraphStyle.alignment = lable.textAlignment
            
            attributedString.addAttribute(NSAttributedString.Key.font, value: lable.font!, range: NSRange(location: 0, length: attributedString.length))
            
            attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
        }
        
        super.titleLabel?.attributedText = attributedString
    }
    
}

+ Recent posts