iOS:當(dāng)圓角和陰影打了一架

最近做到一個(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)糙昼蛀,希望各位大佬多多包涵宴猾,告辭,留步叼旋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仇哆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子夫植,更是在濱河造成了極大的恐慌讹剔,老刑警劉巖油讯,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異延欠,居然都是意外死亡陌兑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)由捎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)兔综,“玉大人,你說(shuō)我怎么就攤上這事狞玛∪沓郏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵心肪,是天一觀的道長(zhǎng)锭亏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)硬鞍,這世上最難降的妖魔是什么慧瘤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮固该,結(jié)果婚禮上锅减,老公的妹妹穿的比我還像新娘。我一直安慰自己蹬音,他們只是感情好上煤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著著淆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拴疤。 梳的紋絲不亂的頭發(fā)上永部,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音呐矾,去河邊找鬼苔埋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蜒犯,可吹牛的內(nèi)容都是我干的组橄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼罚随,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼玉工!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起淘菩,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤遵班,失蹤者是張志新(化名)和其女友劉穎屠升,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體狭郑,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腹暖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了翰萨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脏答。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖亩鬼,靈堂內(nèi)的尸體忽然破棺而出殖告,到底是詐尸還是另有隱情,我是刑警寧澤辛孵,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布丛肮,位于F島的核電站,受9級(jí)特大地震影響魄缚,放射性物質(zhì)發(fā)生泄漏宝与。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一冶匹、第九天 我趴在偏房一處隱蔽的房頂上張望习劫。 院中可真熱鬧,春花似錦嚼隘、人聲如沸诽里。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谤狡。三九已至,卻和暖如春卧檐,著一層夾襖步出監(jiān)牢的瞬間墓懂,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工霉囚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捕仔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓盈罐,卻偏偏與公主長(zhǎng)得像榜跌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盅粪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容