最近做到一個(gè)圓角加陰影的需求,忽然有一陣迷茫纹份,相信很多小伙伴也跟我一樣,第一時(shí)間想到的問(wèn)題就是:我切圓角的時(shí)候直接就把陰影一起切掉了廷痘,還怎么加陰影蔓涧。想到這里我就不由自主的想要問(wèn)一下各位簡(jiǎn)書(shū)大佬。然后得到的答案也是五花八門(mén)笋额,有在底層加個(gè)view的元暴,有在底層加個(gè)layer的。但是這些都不是我心中的最優(yōu)解兄猩,原因有二:
- 第一茉盏,單個(gè)控件加特效為什么會(huì)沖突,為什么需要用兩個(gè)控件來(lái)實(shí)現(xiàn)一個(gè)控件上的特效厦滤。
- 第二援岩,如果我上面的button半透明且需要移動(dòng),你需要將這個(gè)控件封裝掏导,如果你項(xiàng)目里每個(gè)控件都有圓角+陰影的特效享怀,那么你的每個(gè)button都占用兩份內(nèi)存空間。個(gè)人覺(jué)著這極不合理趟咆。
那么問(wèn)題出現(xiàn)在哪呢添瓷?其實(shí)剛才已經(jīng)問(wèn)過(guò)了,問(wèn)題就在于圓角和陰影為什么會(huì)打架值纱。
那么圓角和陰影他們有關(guān)系嗎鳞贷?有那么一丟丟,他們都是通過(guò)layer層實(shí)現(xiàn)的特效虐唠。layer層主要包括三種特效搀愧,還有一種是邊框。這三種效果在控件效果中相當(dāng)常見(jiàn)。
那么我們分別來(lái)看一下圓角和陰影的實(shí)現(xiàn)方法:
陰影的實(shí)現(xiàn)方法很直接咱筛,設(shè)置陰影的四項(xiàng)屬性:顏色搓幌、偏移、透明度迅箩、半徑溉愁。
button.layer.shadowColor = [UIColor blackColor].CGColor;
button.layer.shadowOpacity = 1;
button.layer.shadowRadius = 10.0;
button.layer.shadowOffset = CGSizeMake(5, 5);
這看起來(lái)沒(méi)有問(wèn)題,而且在我們的第一認(rèn)識(shí)里面也認(rèn)為是圓角切掉了陰影饲趋,那么我們?cè)倏磮A角的實(shí)現(xiàn)方法:
button.layer.cornerRadius = 10;
button.layer.masksToBounds = YES;
我們一般習(xí)慣上這么寫(xiě)拐揭,這看起來(lái)似乎也沒(méi)有問(wèn)題,但是寫(xiě)到這里聰明的小伙伴們一定想到了什么:masksToBounds
奕塑,但是細(xì)心的我還是去翻了一下文檔堂污,然后理所當(dāng)然的發(fā)現(xiàn)了點(diǎn)什么,可以讓我的表達(dá)更具說(shuō)服力爵川。
mask
The layer’s alpha channel determines how much of the layer’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through, but fully transparent pixels block that content.
masksToBounds
When the value of this property is YES, Core Animation creates an implicit clipping mask that matches the bounds of the layer and includes any corner radius effects. If a value for the mask property is also specified, the two masks are multiplied to get the final mask value.
也就是說(shuō)敷鸦,mask層并沒(méi)有對(duì)layer本身的圓角屬性進(jìn)行修改,而是創(chuàng)建了一個(gè)剪切蒙版寝贡,默認(rèn)跟layer是一樣的大小,而且包含圓角效果值依,蒙版之外的部分將不會(huì)顯示圃泡。那么在創(chuàng)建蒙版之前,layer的圓角是否已經(jīng)可以顯示了呢愿险?那么我們就要來(lái)看 cornerRadius
了:
Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to YES causes the content to be clipped to the rounded corners.
結(jié)合簡(jiǎn)單的實(shí)踐颇蜡,我們可以確認(rèn)文檔里傳達(dá)的信息,cornerRadius切出的圓角效果是可以直接顯示的辆亏,但是 圖片 除外风秤。
如果你只是一個(gè)擁有背景色的button宵蕉,用cornerRadius設(shè)置圓角烤礁,然后添加陰影顯示鹏溯,不執(zhí)行masksToBounds = YES 當(dāng)然是可以實(shí)現(xiàn)的栋烤,但是敞恋,現(xiàn)實(shí)真的會(huì)如此嗎睦优?不要太天真了佃扼。你連圓角和陰影這樣的效果都加了激涤,讓你區(qū)分一下 normal
衷蜓、highlight
累提、disable
狀態(tài)下不同的背景顏色不過(guò)分吧。那么你會(huì)怎么實(shí)現(xiàn)呢磁浇?或者說(shuō)斋陪,項(xiàng)目中原來(lái)是怎么實(shí)現(xiàn)的呢?
你會(huì)發(fā)現(xiàn),UIButton的backgrouncolor是不區(qū)分state設(shè)置的无虚,如果你想從這個(gè)屬性進(jìn)行區(qū)分鞍匾,那么你就要監(jiān)聽(tīng)這個(gè)button的狀態(tài),但是對(duì)不起骑科,button的state屬性也是不完全開(kāi)放獨(dú)立讀取的橡淑,我們只能獲取到disable的狀態(tài)。也許你會(huì)直接使用更簡(jiǎn)單的backgroundImage屬性咆爽,這個(gè)可以直接區(qū)分狀態(tài)設(shè)置的屬性梁棠,將顏色轉(zhuǎn)成圖片設(shè)置,來(lái)完成這個(gè)不同狀態(tài)下背景色不同的效果斗埂,那么恭喜你符糊,不設(shè)置masksToBounds的情況下,圓角就切不出來(lái)了呛凶,因?yàn)楸尘笆菆D片男娄。
現(xiàn)在問(wèn)題已經(jīng)相當(dāng)明朗,如果你的產(chǎn)品不要求你切換不同狀態(tài)時(shí)的按鈕顏色漾稀,那么你完全可以放心的不去設(shè)置 masksToBounds 模闲,在他們改變主意之前。
如果你既想要圓角加陰影的效果崭捍,又想要炫酷的按鈕背景和多元的按鈕交互尸折,只有一個(gè)辦法:搞圖。
- 如果你的背景不只有顏色殷蛇,還有更加炫酷的花紋实夹,那么一定要讓UI妹子把圓角切出來(lái),而且各種顏色要全粒梦。
- 如果你的按鈕只有背景色亮航,而你們又是用代碼將顏色轉(zhuǎn)化為圖片,那么怎么辦呢匀们?
不要著急缴淋,給你:
- (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andcornerRadius:(CGFloat)radius {
if (!color || size.width <= 0 || size.height <= 0) return nil;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextMoveToPoint(context, size.width, size.height - radius); // 開(kāi)始坐標(biāo)右邊開(kāi)始
CGContextAddArcToPoint(context, size.width, size.height, size.width - radius, size.height, radius); // 右下角角度
CGContextAddArcToPoint(context, 0, size.height, 0, size.height - radius, radius); // 左下角角度
CGContextAddArcToPoint(context, 0, 0, radius, 0, radius); // 左上角
CGContextAddArcToPoint(context, size.width, 0, size.width, radius, radius); // 右上角
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFill);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
畫(huà)一個(gè)帶圓角的嘛!
寫(xiě)的有點(diǎn)糙昼蛀,希望各位大佬多多包涵宴猾,告辭,留步叼旋。