本片文章前三章內容你們比較經常使用,後面的可能會不那麼經常使用,前面的基礎內容不想看了能夠直接從第4段開始html
這個功能仍是很常見的,原本不想記了,爲了整個系列的完整性,仍是囉嗦一下。
CALayer
有一個conrnerRadius
的屬性控制圖層的圓角曲率,默認值爲0。這個曲率值默認隻影響背景顏色而不影響背景圖片或者子圖層。能夠用過下面的示例看一下。ios
在Storyboard
中放置兩個白色的view
,每一個view
分別有兩個子view
(一個黃色,一個青色),並且都超出了父視圖的邊界:git
而後在代碼中寫入以下代碼:性能
@interface ViewController () @property (weak, nonatomic) IBOutlet UIView *leftView; @property (weak, nonatomic) IBOutlet UIView *rightView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.leftView.layer.cornerRadius = 20.f; self.rightView.layer.cornerRadius = 20.f; self.rightView.layer.masksToBounds = YES; } @end
而後運行效果以下:動畫
經過上面的示例能夠發現:atom
cornerRadius
時,默認狀況下,隻影響背景顏色,而不影響背景圖片或者子圖層。masksToBounds
爲YES
。CALayer
另外兩個很是有用的屬性borderWidth
和borderColor
。borderWidth
是以點爲單位定義邊框粗細的浮點數,默認爲0。borderColor
定義了邊框的顏色,默認爲黑色。spa
borderColor
是CGColorRef
類型。
邊框繪製在圖層邊界裏面,在全部子圖層以前。對上面的示例代碼坐下調整:指針
- (void)viewDidLoad { [super viewDidLoad]; self.leftView.layer.cornerRadius = 20.f; self.rightView.layer.cornerRadius = 20.f; self.leftView.layer.borderWidth = 5.f; self.rightView.layer.borderWidth = 5.f; self.rightView.layer.masksToBounds = YES; }
運行效果以下:code
如上面的示例的結果同樣,邊框並不會把寄宿圖或子圖層的相撞計算出來。並且繪製邊框會顯示在最上層。
控制圖層陰影的屬性會比前面的邊框多一些。htm
shadowOpacity
屬性控制陰影透明度的,它是一個在0.0
和1.0
之間的浮點數,若是設置爲1.0
將會顯示一個輕微模糊的陰影。shadowColor
屬性控制着陰影的顏色,和borderColor
同樣,它的類型也是CGColorRef
,陰影默認是黑色的。shadowOffset
屬性控制陰影的方向和距離,它是一個CGSize
的值,寬度控制陰影橫向位移,高度控制縱向位移。默認值是`{0, -3}。shadowRadius
屬性控制着陰影的模糊度,當值爲0
的時候,陰影和視圖同樣有一個明顯的邊界,值越大,邊界線看起來就會越模糊。和圖層邊框不一樣,圖層的陰影繼承自內容的外形,而不是根據邊界來界定。
有個頭疼的限制,陰影一般在Layer
的邊界以外,若是咱們開啓了maskToBounds
以後,全部突出圖層外的內容都會被裁剪到,包括咱們設置的陰影。
以前有個UI需求,同時設置陰影和圓角,圓角簡單的使用layer.cornerRadius
和maskToBounds
。致使一直顯示不出來陰影,差的緣由是沒法共存,到如今才發現是maskToBounds
致使的。
maskToBounds
把陰影也裁掉的結果確定不是咱們想要的。可是在同一個圖層缺又存在這個問題,因此這看起來很簡單的效果,咱們須要用到兩個圖層,一個圖層作maskToBounds
裁剪,一個圖層畫陰影。
下面咱們用圓角下面的那個demo稍做修改作個示例:
首先對rightView
作一個透明色的shadowView
的包裹,用來設置陰影:
將代碼修改爲以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIView *leftView; @property (weak, nonatomic) IBOutlet UIView *rightView; @property (weak, nonatomic) IBOutlet UIView *shadowView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.leftView.layer.cornerRadius = 20.f; self.rightView.layer.cornerRadius = 20.f; self.leftView.layer.borderWidth = 5.f; self.rightView.layer.borderWidth = 5.f; // 不添加其餘圖層直接給 leftView 設置陰影試一試 self.leftView.layer.shadowOffset = CGSizeMake(5, 5); self.leftView.layer.shadowOpacity = 0.8f; self.leftView.layer.shadowRadius = 5.f; // 給 shadowView 添加和 leftview 同樣的陰影效果 self.shadowView.layer.shadowOffset = CGSizeMake(5, 5); self.shadowView.layer.shadowOpacity = 0.8f; self.shadowView.layer.shadowRadius = 5.f; // 將view裁剪 self.rightView.layer.masksToBounds = YES; } @end
運行的效果如圖:
注意看左邊視圖的陰影範圍,很好的說明了圖層的陰影繼承自內容的外形,而不是根據邊界來界定。
圖層陰影並不老是方的,而是從內容的形狀繼承來的。由於計算陰影是一個很耗資源的步驟,尤爲有多個子圖層的時候。若是咱們指定陰影的形狀的話,能夠指定陰影的樣子來節省計算陰影的資源開銷。shadowPath
就是作這個事的,它是一個CGPathRef
類型(指向CGPath
的指針)。
下圖展現了贊成寄宿圖不一樣陰影的設定:
上圖的代碼實現:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *layerView1; @property (weak, nonatomic) IBOutlet UIImageView *layerView2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.layerView1.layer.shadowOpacity = 0.5f; self.layerView2.layer.shadowOpacity = 0.5f; // 添加矩形陰影 CGMutablePathRef squarePath = CGPathCreateMutable(); CGPathAddRect(squarePath, NULL, self.layerView1.bounds); self.layerView1.layer.shadowPath = squarePath; CGPathRelease(squarePath); // 添加圓形陰影 CGMutablePathRef circlePath = CGPathCreateMutable(); CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds); self.layerView2.layer.shadowPath = circlePath; CGPathRelease(circlePath); } @end
若是一個矩形或者圓形,用CGPath
很簡單能夠實現,若是複雜的圖就須要藉助UIBezierPath
來實現了。
這節的原文章前有一堆鋪墊的,我就不說了,想看的 點擊查看原文
本節主要是介紹CALayer
的maskt
屬性,它能夠實現一些比較好玩的裁剪效果。而不是常規的圓形、矩形裁剪。mask
圖層的Color
屬性可有可無,它真正有用的是圖層的輪廓。以下圖所示同樣,mask
屬性像是一個切割機,mask
圖層實心的地方會被保留,其餘地方被拋棄。
下面咱們實現如下上圖的效果,首先在Storyboard
裏建立一個UIImageView
,而後代碼以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 建立mask CALayer *maskLayer = [CALayer layer]; maskLayer.frame = self.imageView.bounds; UIImage *maskImage = [UIImage imageNamed:@"test_mask"]; maskLayer.contents = (__bridge id)maskImage.CGImage; // 添加到 imageview 上 self.imageView.layer.mask = maskLayer; // 兩張圖片素材是在原文中截圖處理的,因此展現的效果和原文有所差異。 } @end
運行效果以下:
CALayer
蒙板圖層不侷限於靜態圖,也能夠經過代碼甚至是動畫實時生成蒙板。
關於這些我看了原文,確實不懂,並且我也沒碰到過,無從下手作筆記。若是想了解的話 請點擊此處
UIView
有一個alpha
屬性來決定視圖的透明度,對應的CALayer
有一個opacity
屬性。這兩個屬性都會影響子層級的顯示透明度。
下面作個示例。如今Storyboard
裏放置兩個UIButton
。而後代碼以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIButton *leftBtn; @property (weak, nonatomic) IBOutlet UIButton *rightBtn; @end @implementation ViewController - (UILabel *)subLbl { UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 90, 40)]; label.text = @"Hello World"; label.backgroundColor = [UIColor whiteColor]; label.textAlignment = NSTextAlignmentCenter; return label; } - (void)viewDidLoad { [super viewDidLoad]; [self.leftBtn addSubview:[self subLbl]]; [self.rightBtn addSubview:[self subLbl]]; self.rightBtn.alpha = 0.5; } @end
運行的效果以下:
這顯示的效果有點怪。右邊的設置了alpha
爲0.5
。可是在UILabel
的位置好像不是0.5
的效果。這是由於透明度的混合疊加形成的。實際上右側中間的透明度是0.75
。
當顯示一個50%透明度的圖層時,圖層的每一個像素都會一半顯示本身的顏色,另外一半顯示圖層下面的顏色。這是正常的透明度的表現。可是若是圖層包含一個一樣顯示50%透明的子圖層時,你所看到的視圖,50%來自子視圖,25%來了圖層自己的顏色,另外的25%則來自背景色。
若是想保持透明度一直。咱們能夠在info.plist
文件中添加UIViewGroupOpacity
並設置成YES
來打到這個效果。還有一種方法就是對CALayer
進行設置。shouldRasterize
屬性能夠實現組透明,若是設置成YES
,圖層和它的子圖層會被合成一個總體圖片。
啓用shouldRasterize
屬性,通常須要同時設置圖層的rasterizationScale
屬性防止出現Retina屏幕像素化的問題。
shouldRasterize和UIViewGroupOpacity一塊兒的時候,會出現性能問題,後面再講。
對上面的展現效果處理的代碼以下:
@interface ViewController () @property (weak, nonatomic) IBOutlet UIButton *leftBtn; @property (weak, nonatomic) IBOutlet UIButton *rightBtn; @end @implementation ViewController - (UILabel *)subLbl { UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 90, 40)]; label.text = @"Hello World"; label.backgroundColor = [UIColor whiteColor]; label.textAlignment = NSTextAlignmentCenter; return label; } - (void)viewDidLoad { [super viewDidLoad]; [self.leftBtn addSubview:[self subLbl]]; [self.rightBtn addSubview:[self subLbl]]; self.rightBtn.alpha = 0.5; self.rightBtn.layer.rasterizationScale = [UIScreen mainScreen].scale; self.rightBtn.layer.shouldRasterize = YES; } @end
效果如咱們所願。