2014-09-21 14 views
2

我目前正在學習如何實現自定義控件。我不可避免地偶然發現了CALayer的可能性,因爲當需要執行復雜的動畫時,使用UIImage並不夠靈活。我想使用UIView作爲CALayer的「容器」,以使它的寬度和高度總是與UIView相同(爲了靈活性)。Swift中的自定義UI元素:繼承CALayer並重寫drawInContext結果pixelated drawing

我分類了CALayer並覆蓋了drawInContext()方法。

這裏是我得到屏幕上的結果: Fuzzy/Pixelated image

圖紙看起來像素化和模糊。我正在使用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() 

} 

}

下面是我如何使用它:

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. 
} 

}

我在做什麼錯在這裏? :(

回答

6

TL;博士:你必須設置圖層的contentsScale的東西比默認1.0大


一層默認爲1的比例因子這改變多大。該層的內容緩衝區是:

適用於[...]和內容經由-drawInContext:提供(即,如果contentsScale是二-drawInContext:將繪製到緩衝器中兩倍大的層邊界)

由於您正在執行具有比設備屏幕更少像素的上下文的自定義繪圖,因此繪圖看起來像素化。對於傳統的「視網膜」屏幕,您期望的比例因子是2.0,但隨着最近推出的iPhone 6+,還有比例因子3.0。好消息是您可以從UIScreen獲得設備規模。

+0

非常感謝David!你是一個絕對的傳奇!你的答案和博客總是充滿知識和智慧。再次 - 謝謝你,先生! – 2014-09-21 12:40:53

+1

確實。就FTR而言,一個常見的,類似的相關問題是,當你(比如說)動畫這樣的東西的大小時,你需要self.layer.shouldRasterize = YES; – Fattie 2014-09-21 12:46:15

+0

嘿@JoeBlow,謝謝!我確實計劃製作很多東西,所以我相信這會派上用場。 – 2014-09-21 13:10:18