前兩天有個讀者告訴我,UIButton進行了圓角切割以後紅點和數字沒法正常顯示:ide
簡單測試了一下,確實有這個問題,由於我本人項目是將Image繪製成圓形,因此沒有發現這個問題,通常不直接對控件進行處理。學習
1.不切割控件,將Image繪製成須要的圓形:測試
//圖像圓角切割 - (UIImage *)ymtGetCornerRadius:(CGFloat)cornerRadius { CGFloat scale = [UIScreen mainScreen].scale; UIGraphicsBeginImageContextWithOptions(self.size, NO, scale); CGContextRef c = UIGraphicsGetCurrentContext(); CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; CGContextAddPath(c, path.CGPath); CGContextClip(c); [self drawInRect:rect]; CGContextDrawPath(c, kCGPathFillStroke); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
2.在button外面套一個空白的view,紅點顯示在view上:spa
圖層以下:code
相信不少開發者遇到過按鈕或圖片右上角須要顯示紅點/數字的需求。orm
前段時間,公司項目加入了新聞資訊功能,要求收到普通新聞在新聞logo右上角顯示紅點,重磅消息在logo右上角顯示收到的重磅消息的數量,效果以下圖:繼承
方法有不少,好比:寫個Label加入cell中放在圖片右上角、切換圖片等等,本文使用Category對Class進行擴展的方法實現該需求,適用於各類view。圖片
先上代碼。ip
UIView+redPoint.h文件代碼以下,分別給出show方法和hide方法:ci
// // UIView+redPoint.h // Medicine // // Created by zhujiamin on 16/4/16. // Copyright © 2016年 MedEx. All rights reserved. // #import <UIKit/UIKit.h> @interface UIView (redPoint) - (void)showRedAtOffSetX:(float)offsetX AndOffSetY:(float)offsetY OrValue:(NSString *)value; - (void)hideRedPoint; @end
UIView+redPoint.m文件中具體方法實現以下:
#pragma other(redPoint) //添加顯示 - (void)showRedAtOffSetX:(float)offsetX AndOffSetY:(float)offsetY OrValue:(NSString *)value{ [self removeRedPoint];//添加以前先移除,避免重複添加 //新建小紅點 UIView *badgeView = [[UIView alloc]init]; badgeView.tag = 998; CGFloat viewWidth = 12; if (value) { viewWidth = 18; UILabel *valueLbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, viewWidth, viewWidth)]; valueLbl.text = value; valueLbl.font = FONT_12; valueLbl.textColor = [UIColor whiteColor]; valueLbl.textAlignment = NSTextAlignmentCenter; valueLbl.clipsToBounds = YES; [badgeView addSubview:valueLbl]; } badgeView.layer.cornerRadius = viewWidth / 2; badgeView.backgroundColor = [UIColor redColor]; CGRect tabFrame = self.frame; //肯定小紅點的位置 if (offsetX == 0) { offsetX = 1; } if (offsetY == 0) { offsetY = 0.05; } CGFloat x = ceilf(tabFrame.size.width + offsetX); CGFloat y = ceilf(offsetY * tabFrame.size.height); badgeView.frame = CGRectMake(x, y, viewWidth, viewWidth); [self addSubview:badgeView]; } //隱藏 - (void)hideRedPoint{ [self removeRedPoint]; } //移除 - (void)removeRedPoint{ //按照tag值進行移除 for (UIView *subView in self.subviews) { if (subView.tag == 998) { [subView removeFromSuperview]; } } }
爲了知足不一樣位置的顯示
- (void)showRedAtOffSetX:(float)offsetX AndOffSetY:(float)offsetY OrValue:(NSString *)value;
此方法接收調用時給入想要顯示的紅點或者數字相對父view的最大X值的偏移,和高度的倍數;
if (offsetX == 0) { offsetX = 1; } if (offsetY == 0) { offsetY = 0.05; } CGFloat x = ceilf(tabFrame.size.width + offsetX); CGFloat y = ceilf(offsetY * tabFrame.size.height);
默認須要顯示在右上角時,offsetX和offsetY能夠設置爲0,根據具體需求給出不一樣的數值便可;
本例須要Button右上角顯示紅點,須要顯示紅點時Value值賦爲nil,若需顯示數字則賦值相應的字符便可,調用方法以下:
[centerBtn showRedAtOffSetX:0 AndOffSetY:0 OrValue:nil]; [centerBtn showRedAtOffSetX:0 AndOffSetY:0 OrValue:@"2"];
須要隱藏紅點/數字時只須要調用
[sender hideRedPoint];
方法將其移除便可。
實現這個需求的時候,我想到先前作的底部tabbar下的item顯示紅點的方法,使用的是粗暴的切換圖片方法,實際上UITabbar也繼承於UIView,這種思路一樣適用,不過tabbar只須要顯示和隱藏紅點便可,顯示數字使用系統的badgeValue賦值便可,效果以下:
因而我在UIView+redPoint.h文件中加入瞭如下兩個方法供UITabbar調用,index參數爲要顯示紅點的item的序號。
//tabbar方法 - (void)showBadgeOnItemIndex:(int)index; //顯示小紅點 - (void)hideBadgeOnItemIndex:(int)index; //隱藏小紅點
具體實現方法和前面講到的其餘控件顯示方法相似,只不過要準確計算顯示紅點的位置,具體實現以下:
#define USERDEF [NSUserDefaults standardUserDefaults] //宏定義NSUserDefaults用來存本地標記
#pragma mark Tabbar(redPoint) //顯示小紅點 - (void)showBadgeOnItemIndex:(int)index{ NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; if ([USERDEF objectForKey:keyStr]) { return; } else { [USERDEF setObject:@"HADSET" forKey:keyStr]; } //移除以前可能存在的小紅點 [self removeBadgeOnItemIndex:index]; //新建小紅點 UIView *badgeView = [[UIView alloc]init]; badgeView.tag = 888 + index; badgeView.layer.cornerRadius = 6; badgeView.backgroundColor = [UIColor redColor]; CGRect tabFrame = self.frame; //肯定小紅點的位置 float percentX = (index +0.55) / 5; //5爲tabbaritem的總個數 CGFloat x = ceilf(percentX * tabFrame.size.width); CGFloat y = ceilf(0.05 * tabFrame.size.height); badgeView.frame = CGRectMake(x, y, 12, 12); [self addSubview:badgeView]; } //隱藏小紅點 - (void)hideBadgeOnItemIndex:(int)index{ NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; //移除小紅點 [self removeBadgeOnItemIndex:index]; if ([USERDEF objectForKey:keyStr]) { [USERDEF removeObjectForKey:keyStr]; } } //移除 - (void)removeBadgeOnItemIndex:(int)index{ //按照tag值進行移除 for (UIView *subView in self.subviews) { if (subView.tag == 888+index) { [subView removeFromSuperview]; } } }
由於tabar紅點設置方法調用比較頻繁,爲了不每次重複移除重設操做,我在紅點show成功以後會對當前item進行本地標記,每次調用showBadgeOnItemIndex:方法會先判斷當前index是否已經顯示紅點,已經顯示則不在重複設置,調用hideBadgeOnItemIndex:方法時,移除該標記。
NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; if ([USERDEF objectForKey:keyStr]) { return; } else { [USERDEF setObject:@"HADSET" forKey:keyStr]; }
NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; if ([USERDEF objectForKey:keyStr]) { [USERDEF removeObjectForKey:keyStr]; }
顯示/隱藏調用方法以下:
[self.tabBarController.tabBar showBadgeOnItemIndex:4]; //"個人"顯示紅點 [self.tabBarController.tabBar hideBadgeOnItemIndex:4]; //"個人"移除紅點
分享完畢。
本人座標杭州,後續我會陸續把工做中遇到的問題及解決方案分享出來,互相交流學習,本人QQ:815187811,歡迎結交[笑臉].