1
votes

I want to create a custom button in swift and the result is not quite satisfying. UIBezierpath is not drawing a smooth path. Please see image and code below.

let roundRect = UIBezierPath(roundedRect: CGRectMake(0, 0, 156, 60), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))

rendered result: image1

After playing around a little bit, I found that moving the path down and right 1 point and shrinking the rectangle size by 1 will solve the problem. but I don't like this solution, I don't think this is the correct way of doing it. And I feel like the frame is clipping my image. Can someone help me with this??

let roundRect = UIBezierPath(roundedRect: CGRectMake(1, 1, 154, 59), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))

rendered result: image2

the whole CustomButton Subclass:

import UIKit

class DesignableButtons: UIButton {
    let black = UIColor(red: 33/255, green: 33/255, blue: 33/255, alpha: 1.0) /* #212121 */

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        self.setTitle("Go to Google", forState: UIControlState.Normal)
        self.titleLabel!.font = UIFont(name: "GT Walsheim", size: 14)
        self.setTitleColor(black, forState: .Normal)
        self.setTitleColor(UIColor.whiteColor(), forState: .Highlighted)
        self.setTitleColor(UIColor.whiteColor(), forState: .Selected)
        self.titleLabel!.alpha = 1.0
    }

    let roundRect = UIBezierPath(roundedRect: CGRectMake(0, 0, 156, 60), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))

    override func drawRect(rect: CGRect) {
        black.setStroke()
        roundRect.stroke()
        if highlighted {
            black.setFill()
            roundRect.fill()
        }
    }

    override var highlighted: Bool {
        didSet {
            setNeedsDisplay()
        }
    }
}
2
Can you please post all of your drawing code? Also, does this reproduce on a physical device? Sometimes this happens on the simulator if you're not zoomed to 100%.Aaron Brager
yes the same thing does happen on my physical iphone6.Kenneth Huang
override func drawRect No. It is not permitted to override drawRect for a UIButton. You need to construct a background image and set the button's background image and let it do the drawing in its own way.matt

2 Answers

2
votes

Try this

let roundRect = UIBezierPath(roundedRect: CGRectInset(CGRectMake(0, 0, 156, 60), 1, 1), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))

EDITED

or you can also do this to do it more reusable, this in your layoutSubviews

let roundRect = UIBezierPath(roundedRect: CGRectInset(self.frame, 1, 1), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))

Instead of

let roundRect = UIBezierPath(roundedRect: CGRectMake(0, 0, 156, 60), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))

the CGRectInset function create a rect inside your original rect,

Returns a rectangle that is smaller or larger than the source rectangle, with the same center point.

EDITED you can put this in your init to fix the visualization issue

self.contentScaleFactor = UIScreen.mainScreen().scale //SUPPORT RETINA

I hope this help you

1
votes

You have problem because lines was been clipped. When you drawing into drawRect: this happen an always. Try drawing outside drawRect:.

For example:

required init?(coder aDecoder: NSCoder) {
    // some code
    layer.masksToBounds = true
    layer.cornerRadius = 200
    layer.borderWidth = 1
    layer.borderColor = black.CGColor
}

Or if you want using sublayers:

let borderLine = CAShapeLayer()

required init?(coder aDecoder: NSCoder) {
    // some code
    frame = someFrame

    let roundRect = UIBezierPath(roundedRect: CGRectMake(0, 0, 156, 60), byRoundingCorners:.AllCorners, cornerRadii: CGSizeMake(200, 200))
    borderLine.path = roundRect.CGPath
    borderLine.frame = bounds
    borderLine.strokeColor = black.CGColor
    borderLine.fillColor = UIColor.clearColor().CGColor
    borderLine.lineWidth = 1

    layer.insertSublayer(borderLine, atIndex: 0)
}