2
votes

I'm currently learning how to implement custom controls. I inevitably stumbled upon the CALayer possibility, as using UIImage is not flexible enough when complex animations need to be performed.

I want to use UIView as a "container" for a CALayer so that its width and height are always the same as the UIView (for flexibility purposes).

I subclassed CALayer and overwrote the drawInContext() method.

Here's the result I'm getting on screen: Fuzzy / Pixelated image

The drawing looks pixelated and fuzzy. I am using PaintCode to generate the drawing code for me.

Here's the custom CALayer:

class SegmentActive: CALayer {

func frameSetup() -> CGRect {

    let frameWidth:CGFloat = superlayer.frame.width
    let frameHeight:CGFloat = superlayer.frame.height

    let frame = CGRectMake(0, 0, frameWidth, frameHeight)

    println("\(superlayer.frame.width) // \(superlayer.frame.height)")

    return frame

}

override func drawInContext(ctx: CGContext!) {

    UIGraphicsPushContext(ctx)

    CalorieCalculatorUI.drawSegControlActiveBase(frameSetup())

    UIGraphicsPopContext()

}

}

And here's how I use it:

class ViewController: UIViewController {

@IBOutlet weak var leftSegmentUIView: UIView!

override func viewDidLoad() {

    let activeSegment:SegmentActive = SegmentActive()

    leftSegmentUIView.layer.addSublayer(activeSegment)

    activeSegment.frame = activeSegment.frameSetup()

    activeSegment.setNeedsDisplay()

    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

What am I doing wrong here? :(

1

1 Answers

7
votes

tl;dr: You have to set contentsScale of the layer to something larger than the default 1.0.


The scale factor of a layer defaults to 1. This changes how large the content buffer for that layer is:

Applies to [...] and content provided via -drawInContext: (i.e. if contentsScale is two -drawInContext: will draw into a buffer twice as large as the layer bounds)

Since you are doing custom drawing into context that has fewer pixels than the devices screen, the drawing looks pixelated. For traditional "retina" screens, the scale factor you are expecting is 2.0 but with the recent introduction of the iPhone 6+ there is also the scale factor of 3.0. The good news is that you can get the device scale from UIScreen.