因為項目需要,整理了下圓角和邊框輔助類。想起前幾天標哥還在微博里問圓角在tableView里卡頓的問題,想着去炫耀下。去到標哥的博客,發現已經有一定程度解決,給出開源庫並且在推廣,迭代了好幾個版本了。。
圓角這東西被無數性能追求者津津樂道,無數小白們高山仰止。 至於圓角的幾種實現方案,設置cornerRadius、加maskLayer、直接加鏤空圖、內存異步裁剪等等,網絡上一搜一大把,這里就不再重復了。這里有兩點要提醒下,紋理裁剪才是off-screen rendering的原因,而不是設置圓角。當然你要是作死的去設了layer的fillColor,再來設圓角,那就只能說no zuo no die ;另外在使用光柵化時,一定要設置scale以適配屏幕分辨率。
既然標哥都給出開源方案了,那就比較一下,檢查下自己的不足吧。為參照相同的運行條件,筆者把自己寫的輔助類放到標哥的Demo里,實現相同的效果。然后從設計思路、外觀呈現、CPU和內存、幀速、代碼量、侵入性和易用性、適用場景等多個方面做出比較。
標哥的開源庫:https://github.com/CoderJackyHuang/HYBImageCliped
筆者fork后修改的項目:https://github.com/1962449521/HYBImageCliped
該功能類的在線維護:https://github.com/1962449521/WHUCornerMaker
筆者整理中的輔助類集:https://github.com/1962449521/WHUKit/tree/master/WHUKitDemo/WHUKitDemo/WHUKit
以下為筆者方案與標哥開源庫的比較
一、 突破口的選擇
標哥選擇的起點是內存中剪裁圖片,通過緩存策略以優化性能,給UIView、UIImageView、UIButton等控件增加Category以擴展功能。筆者選擇的起點是繪制鏤空圖,同樣使用了緩存以提高復用。因為長期開發SDK盡量不使用Category的習慣,筆者采用輔助類的形式提供功能實現。
二、 功能及解決問題
主要的出發點都是為了解決圓角圖片離屏渲染影響滑動幀速的問題。標哥采用了剪裁圖片的方式,能夠適應背景非單色情況;在控件內部的圖片,能提供圓角效果,比如按鈕內非抵邊的image;在邊線的繪制上,提供了形狀邊框,邊框有填充和邊線。筆者提供的輔助類只適用背景單色,裁剪針對UIView或其子類整體,邊線只提供單線。
三、 外觀呈現
除了雙色邊線外,其它的外觀都能做到相同的效果。
![]() |
![]() |
標哥靜態容器 | 筆者靜態容器 |
![]() |
![]() |
標哥collectionView | 筆者collectionView |
四、CPU和內存
標哥方案CPU使用驟增,最高達到82%。內存使用也高於筆者。因為筆者采用了每次cell出現時重繪邊角,所以CPU略高。如果確定每次cell重用時邊角位置正確,可以不重繪邊角,CPU能穩定在13%左右。圖片相對較少,內存使用差別不明顯。當不同圖片較多時,標哥使用方案需大量緩存裁切好的圖片,猜測會在內存使用上隨之增加。而筆者方案會復用相同角度顏色的邊角,圖片增多時不會增加圓角圖片的內存開銷。
![]() |
標哥方案 |
![]() |
筆者方案 |
五、 幀速
滑動幀速基本相近,都有較好的體驗,筆者方案數值相對較高。
![]() |
標哥方案 |
![]() |
筆者方案 |
六、代碼量
標哥使用了一個管理類HYBImageClipedManager,以及提供了UIImage、UIView、UIButton三個類的category,總共約1千行代碼。筆者提供了WHUCornerMaker、WHUBorderMaker兩個輔助功能類,約250行代碼。
七、侵入性和易用性
以下為筆者兩個輔助類的頭文件聲明和暴露的使用API,自認為還是較為清晰易用的。這里要說到關於注釋,多余的注釋是違反DRY原則的,不過由於國人對英文的理解不直接或者項目編碼約定,而加了許多不必要的注釋。還是應當以清晰符合語義的方法、變量命名作為首選。至於標哥提供的接入設計,方法太多就不在這里列出了,感興趣的童鞋可以從本文提供的鏈接跳入查看^^
@interface WHUCornerMaker : NSObject + (BOOL) isCorneredAtView:(UIView * _Nonnull)view; // 優先選取view 沿superview上的父類容器的背景色, 如果一直為nil, 則取defaultColor 作為圓角顏色 - (void) roundView:( UIView * _Nonnull ) view withCornerRadius:(CGFloat) radius defaultColor:( UIColor * _Nullable)color; - (void) roundViews:(NSArray<UIView *> * _Nonnull) views withCornerRadius:(CGFloat) radius defaultColor:( UIColor * _Nullable)color; - (void) roundView:(UIView * _Nonnull) view withCornerRadius:(CGFloat) radius defaultColor:( UIColor * _Nullable)color byRoundingCorners:(UIRectCorner)corners; - (void) roundViews:(NSArray<UIView *> * _Nonnull) views withCornerRadius:(CGFloat) radius defaultColor:( UIColor * _Nullable)color byRoundingCorners:(UIRectCorner)corners; @end
@interface WHUBorderMaker : NSObject + (void) borderView:( UIView * _Nonnull ) view withCornerRadius:(CGFloat) radius width:(CGFloat)borderWidth color:(UIColor * _Nonnull)borderColor; + (void) borderView:( UIView * _Nonnull ) view withCornerRadius:(CGFloat) radius width:(CGFloat)borderWidth color:(UIColor * _Nonnull)borderColor byRoundingCorners:(UIRectCorner)corners; @end
八、適用場景
不可否認,標哥提供了更多功能,比如拿到裁切的圖片,繪制雙色邊框等。不過這樣的使用場景應該是較少的,筆者提供了輔助類能滿足大多數場景的需求。
九、總結
在做通用性開源庫的時候,可能會考慮更多的東西。但花80%的精力去實現5%使用者的需求是否有必要是有待斟酌的。在筆者方案和標哥方案的比較中,總體而言筆者的方案性能是高出很多,並不隨使用條件復雜性的增加而性能降低。這一方面是內存裁剪圖片本就是騎虎難下的選擇,一方面也是筆者只針對有限的使用場景和需求。