iOS中矩形視圖顯示圓形區域

前段時間項目中有個特殊的需求,折騰了好久,覺得有必要總結一下。我自己寫了一個日歷控件,產品要求選中的日期要用圓形圖片顯示出來,如圖所示


圖1.jpeg

方案一

剛開始以為只要用layer.cornerRadius就可以了,但是真正實現起來的時候才發現不是那么簡單。因為我的日歷控件寬度設置為屏幕寬度,那么問題就來了,日歷一行只能顯示七天,所以不同屏幕寬度下每個單元view的寬度就不固定了,而且還不是正方形,用layer.cornerRadius的話就會出來一個橢圓形的選中效果,第一種方案就放棄了。

方案二

第二種方案我是想著放一個遮罩,既然itemView不一定是正方形,那我們想辦法讓它只顯示出來正方形的區域就好了。于是用UIBezierPath+CAShapeLayer畫出一個圓形的遮罩添加在每個單元view的layer上,設置為itemView.layer.mask為畫出的圓形CAShapeLayer,運行一看滿足了要求。但出現一個新的問題就是,每次進到這個界面的時候屏幕都會卡頓,能看出明顯的抖動,這肯定是不能忍的。只能查找原因優化~
大概原因是設置layer的mask屬性會觸發離屏渲染,大大的消耗了性能,所以卡頓。其中有一種優化方案就是開啟GPU的柵格化,然后把需要渲染的畫面緩存起來,等下次進來的時候可以直接加載

 self.layer.shouldRasterize = YES;
 self.layer.rasterizationScale = self.layer.contentsScale;

試了一下果然不卡了,但是新的問題又出現了,就是日歷上的數字都變得模糊了。我推斷出大概是以下原因,當shouldRasterize設成true時,layer被渲染成一個bitmap,并緩存起來,等下次使用時不會再重新去渲染了。實現圓角本身就是在做顏色混合(blending),如果每次頁面出來時都blending,消耗太大,這時shouldRasterize = yes,下次就只是簡單的從渲染引擎的cache里讀取那張bitmap,節約系統資源。我這邊要渲染的是文字,估計在layer被渲染成bitmap的過程或者讀取bitmap的時候產生了一些誤差,所以導致文字看上去有些模糊。
接著優化~

方案三

我在itemView上邊覆蓋一個中間為圓形透明區域的圖片,正方形的圖片中心點與itemView的中心點重合。這樣解決了卡頓問題,而且也很清晰,但是新的問題出現了,就是我選中的時候要改變itemView的顏色,這時候如果itemView寬度大于高度的時候,就會出現左右兩邊的顏色沒有被覆蓋的情況,沒辦法……
接著優化~

方案四

反向選取區域,既然處理不了中間的圓形區域,那我能不能把周圍的處理一下嘞~最后終于是功夫不負有心人,就是這個方法bezierPathByReversingPath,用代碼說話吧

- (void)drawRect:(CGRect)rect{
    [super drawRect:rect];
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat radius = MIN(self.width, self.height)*0.5-2;
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.bounds];
    UIBezierPath *clipPath = [[UIBezierPath bezierPathWithRoundedRect:CGRectMake((self.width-radius*2)*0.5, (self.height-radius*2)*0.5, radius*2, radius*2) cornerRadius:radius] bezierPathByReversingPath];
    [path appendPath:clipPath];
    CGContextAddPath(context, path.CGPath);
    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextFillPath(context);
}

我自定義了一個繼承自UILabel的GRCalendarTileLabel控件,在drawRect方法中把中間圓形區域以外的區域設置為了白色,這樣一來不管你外邊是什么形狀,我只留出中間一塊兒圓形區域,這里記得調用[super drawRect:rect]方法,不然給Label設置text的時候是不會顯示的。如下圖所示


圖2.jpeg

這樣一來,問題就算完美解決了。雖然過程中費了不少周折,但是問題解決的時候還是很有成就感滴,特此記錄總結一下,希望能給有同樣需求的小伙伴一點幫助,歡迎大家積極提出指導意見~~~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 每個UIView有一個伙伴稱為layer,一個CALayer。UIView實際上并沒有把自己畫到屏幕上;它繪制本身...
    shenzhenboy閱讀 3,155評論 0 17
  • 轉載:http://www.lxweimin.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,307評論 0 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,287評論 25 708
  • 1.xcode5和xcode7區別 1.xcode7沒有Frameworks文件夾,xcode7內部會自動幫你導入...
    彼岸的黑色曼陀羅閱讀 526評論 0 2
  • 漫天黃沙,依然想出來走走。 一個人走在嘈雜的街,呼嘯而過的風,又怎會讀懂一顆叮叮當當的心。迎面走來一對...
    蘭貴人閱讀 230評論 0 1