Swift中的自定义UI元素:子类化CALayer并覆盖drawInContext会导致像素化绘图

Mar*_*ski 2 calayer uiview ios ios7 swift

我目前正在学习如何实现自定义控件.我不可避免地偶然发现了CALayer的可能性,因为当需要执行复杂的动画时,使用UIImage并不够灵活.

我想使用UIView作为CALayer的"容器",使其宽度和高度始终与UIView相同(出于灵活性目的).

我将CALayer子类化并覆盖了drawInContext()方法.

这是我在屏幕上得到的结果: 模糊/像素化图像

该图看起来像素化和模糊.我正在使用PaintCode为我生成绘图代码.

这是自定义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()

}
Run Code Online (Sandbox Code Playgroud)

}

以下是我如何使用它:

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.
}
Run Code Online (Sandbox Code Playgroud)

}

我在这做错了什么?:(

Dav*_*ist 6

tl; dr:您必须contentsScale将图层设置为大于默认值1.0的值.


图层的比例因子默认为1.这会更改该图层的内容缓冲区的大小:

适用于[...]和通过提供的内容-drawInContext:(即如果contentsScale两个-drawInContext:将绘制到两倍于图层边界的缓冲区)

由于您在自定义绘图中进行了比设备屏幕更少像素的上下文,因此绘图看起来像素化.对于传统的"视网膜"屏幕,您期望的比例因子是,2.0但最近推出的iPhone 6+也有比例因子3.0.好消息是你可以从中获得设备规模UIScreen.