新增小紅點給Tabbar或UIview右上角、文字文字、數字文字 、切圓角
這兩天在搞給tabbar或常規控制元件新增小圓點、數字文字、純文字的需求。使用了Masnory這個庫對常規控制元件新增約束有一個巨大的坑,就是無法及時獲取到常規控制元件的x和y。但是可以及時獲取到常規控制元件的w和h。
這就導致瞭如果使用masnory約束之後的控制元件,無法把什麼紅點、文字文字、數字文字直接作為子檢視新增到目標控制元件上,列位看官請耐心的看下去。
如果是常規控制元件的常規操作的話是可以把小紅點作為子檢視直接新增到目標空間上的,但是在iOS開發中我們經常會遇到常規控制元件有切圓角等一些操作,尤其是不規則圓角,那麼我們使用了UIBezierPath和CAShaperlayer結合的方式對目標控制元件做了切圓角操作。這就使得目標控制元件的layer層經過了.mask的操作,對layer層進行了切割,使得目標控制元件的右上角無法渲染任何子檢視。故而我這裡無法將之作為子檢視直接新增到目標控制元件上。
於是我們換一個思路,生成一個與目標控制元件同樣大小的view,新增到目標控制元件的父檢視上,把目標控制元件蓋起來,然後,再把小紅點什麼的新增到新生成的view上。
先來看看效果:
我在這裡封裝了兩個category分別針對tabbar和常規控制元件
程式碼如下:
UITabBar+XLRedBadge.h
// // UITabBar+XLRedBadge.h // Protostar // // Created by 磊懷王 on 2018/12/4. // NS_ASSUME_NONNULL_BEGIN @interface UITabBar (XLRedBadge) /** 顯示小紅點 * index 表示這是第幾個tabbaritem */ - (void)showBadgeOnItemIndex:(int)index; /** * 隱藏小紅點 * index 表示這是第幾個tabbaritem */ - (void)hideBadgePointOnItemIndex:(int)index; /** * 展示純數字 文字 提示框 * redNum 數字文字 可以是 : 88 99+ 等 * index 確定是哪個tabbaritem */ - (void)showBadgeWithNum:(int)redNum itemInedx:(int)index; /** * 隱藏純數字文字 提示框 */ - (void)hidenBadgeWithNumItemIndex:(int)index; /** * 展示文字文字提示框 * text @"開寶箱" 文字 * index 確定是哪個tabbaritem */ - (void)showBadgeWithText:(NSString *)text itemInedx:(int)index; /** * 隱藏純文字本提示框 */ - (void)hidenBadgeWithTextItemIndex:(int)index; @end NS_ASSUME_NONNULL_END
UITabBar+XLRedBadge.m
// // UITabBar+XLRedBadge.m // Protostar // // Created by 磊懷王 on 2018/12/4. // #import "UITabBar+XLRedBadge.h" //該引數表示 底部有幾個tabbaritem #define TabbarItemNums 3.0 @implementation UITabBar (XLRedBadge) //顯示小紅點 - (void)showBadgeOnItemIndex:(int)index{ //移除之前的小紅點 [self removeBadgeOnItemIndex:index]; //新建小紅點 UIView *badgeView = [[UIView alloc]init]; badgeView.backgroundColor = [UIColor redColor]; badgeView.tag = 888 + index; CGRect tabFrame = self.frame; //確定小紅點的位置 float percentX = (index + 0.55) / TabbarItemNums; CGFloat x = ceilf(percentX * tabFrame.size.width); CGFloat y = ceilf(0.08 * tabFrame.size.height); badgeView.frame = CGRectMake(x, y, 12, 12);//圓形大小為10 [self addRedPointToTab:badgeView]; [self addSubview:badgeView]; } //隱藏小紅點 - (void)hideBadgePointOnItemIndex:(int)index{ //移除小紅點 [self removeBadgeOnItemIndex:index]; } //移除小紅點 - (void)removeBadgeOnItemIndex:(int)index{ //按照tag值進行移除 for (UIView *subView in self.subviews) { if (subView.tag == 888+index) { [subView removeFromSuperview]; } } } //展示數字文字 - (void)showBadgeWithNum:(int)redNum itemInedx:(int)index{ UILabel * numLab = [[UILabel alloc] init]; numLab.tag = 999 + index; CGRect tabFrame = self.frame; //文字框位置 float percentX = (index + 0.53) / TabbarItemNums; CGFloat x = ceilf(percentX * tabFrame.size.width); CGFloat y = ceilf(0.02 * tabFrame.size.height); numLab.frame = CGRectMake(x, y, 20, 20);//圓形大小為10 [self addSubview:numLab]; [self addTextOfNumToTabbar:@"99+" targetView:numLab]; } //隱藏數字文字 - (void)hidenBadgeWithNumItemIndex:(int)index{ for (UIView *subView in self.subviews) { if (subView.tag == 999 + index) { [subView removeFromSuperview]; } } } //展示文字 - (void)showBadgeWithText:(NSString *)text itemInedx:(int)index{ UILabel * numLab = [[UILabel alloc] init]; numLab.tag = 777 + index; CGRect tabFrame = self.frame; //文字框位置 float percentX = (index + 0.55) / TabbarItemNums; CGFloat x = ceilf(percentX * tabFrame.size.width); CGFloat y = -8; numLab.frame = CGRectMake(x, y, 20, 20);//圓形大小為10 [self addSubview:numLab]; [self addTextOfStringToTabbar:@"哈哈哈" targetView:numLab]; } //隱藏文字文字 - (void)hidenBadgeWithTextItemIndex:(int)index{ for (UIView *subView in self.subviews) { if (subView.tag == 777 + index) { [subView removeFromSuperview]; } } } @end
UIView+XLCustomCircularBead.h
//
// UIView+XLCustomCircularBead.h
// goldline
//
// Created by 磊懷王 on 2018/11/29.
// Copyright © 2018 磊懷王. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (XLCustomCircularBead)
/**
* 設定控制元件 圓角帶邊框
* targetview 目標控制元件
* cornerRadius 圓角尺寸
* borderColor 邊框顏色
* borderWidth 邊框寬度
*/
- (void)XLCustomCirclarWithBorad:(UIView *)targetView
cornerRadius:(CGFloat)cornerRadius
borderColor:(UIColor *)borderColor
borderWidth:(CGFloat)borderWidth;
/**
* 繪製圓形控制元件
* targetView 目標控制元件
* cornerRadius 圓角尺寸
*/
- (void)XLCustomCirclar:(UIView *)targetView;
/**
* 繪製全圓角控制元件
* targetView 目標控制元件
* cornerRadius 圓角尺寸
*/
- (void)XLCustomViewAllBeadCircular:(UIView *)targetView
cornerRadius:(CGFloat)cornerRadius;
/**
* 繪製單邊圓角
* targetview 目標控制元件
* cornerRadius 圓角尺寸
* corners 單邊型別
*/
- (void)XLCustomViewSingleBeadCircular:(UIView *)targetView
cornerRadius:(CGFloat)cornerRadius
roundingCorners:(UIRectCorner)corners;
/**
* 給tabbar控制元件新增小紅點
* targetview 目標控制元件
*/
- (void)addRedPointToTab:(UIView *)targetView;
/**
* 給 tabbar 新增 數字文字提示框
* target 目標控制元件
* text 文字
*/
- (void)addTextOfNumToTabbar:(NSString *)text
targetView:(UILabel *)targetV;
/**
* 給tabbar 新增 文字文字提示框
* target 目標控制元件
* text 文字
*/
- (void)addTextOfStringToTabbar:(NSString *)text
targetView:(UILabel *)targetV;
/**
* 給常規控制元件 右上角新增小紅點
* targetview 目標控制元件
* block 需要新增約束的block 注意:該引數使得新增的約束與目標控制元件的約束一致即可。如果是給button上新增約束則
需使得該block中的button也要實現目標控制元件的方法。
* 注:移除小紅點需要設定目標控制元件的tag值 小紅點以7000作為tag基值,使用者使用過程中可隨意設定tag值
*/
- (void)addRedPointCionven:(UIView *)targetView
mas_makeConstraints:(void(^)(UIButton * tempV,NSNumber * helfH))block;
/**
* 移除常規控制元件小紅點
* targetV : 目標控制元件
*/
- (void)removeRedPoint:(UIView *)targetV;
/** 給常規控制元件 新增純數字提示框
* numText 可以是任意數字 88 or 99+
* targetV 目標控制元件
* 需要新增約束的 block
* 注:移除純數字需要設定目標控制元件的tag值 小紅點以8000作為tag基值,使用者使用過程中可隨意設定tag值
*/
- (void)addTextOfNumToCionven:(UIView *)targetView
textNum:(NSString *)numText
mas_makeConstraints:(void(^)(UIView * tempV))block;
/**
移除數字文字提示框
@param targetV 目標控制元件
*/
- (void)removeNumText:(UIView *)targetV;
/**
* 給常規控制元件 新增純文字提示框
* targetv 目標控制元件
* textStr 目標文字
* block 需要新增約束的block 注意:該引數使得新增的約束與目標控制元件的約束一致即可。如果是給button上新增約束則
需使得該block中的button也要實現目標控制元件的方法。
注:移除文字需要設定目標控制元件的tag值 小紅點以9000作為tag基值,使用者使用過程中可隨意設定tag值
*/
- (void)addTextOfStringToCionven:(UIView *)targetV
textString:(NSString *)textStr
mas_makeConstraints:(void(^)(UIButton * tempV,NSNumber * height))block;
/**
移除文字提示框
@param targetV 目標控制元件
*/
- (void)removeStrText:(UIView *)targetV;
@end
NS_ASSUME_NONNULL_END
UIView+XLCustomCircularBead.m
//
// UIView+XLCustomCircularBead.m
// goldline
//
// Created by 磊懷王 on 2018/11/29.
// Copyright © 2018 磊懷王. All rights reserved.
//
#import "UIView+XLCustomCircularBead.h"
@implementation UIView (XLCustomCircularBead)
- (void)XLCustomViewSingleBeadCircular:(UIView *)targetView cornerRadius:(CGFloat)cornerRadius roundingCorners:(UIRectCorner)corners{
// 建立貝塞爾曲線,指定繪製區域、角和角半徑
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:targetView.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];
// 初始化shapeLayer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
// 設定繪製路徑
shapeLayer.path = bezierPath.CGPath;
// 將shapeLayer設定為targetview的layer的mask(遮罩)
targetView.layer.mask = shapeLayer;
}
- (void)XLCustomViewAllBeadCircular:(UIView *)targetView cornerRadius:(CGFloat)cornerRadius{
// 建立貝塞爾曲線,指定繪製區域、角和角半徑
// 繪製4個角,指定角半徑
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:targetView.bounds cornerRadius:cornerRadius];
// 繪製圓
// bezierPath = [UIBezierPath bezierPathWithOvalInRect:imageView2.bounds];
// 初始化shapeLayer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
// 設定繪製路徑
shapeLayer.path = bezierPath.CGPath;
// 將shapeLayer設定為targetview的layer的mask(遮罩)
targetView.layer.mask = shapeLayer;
}
- (void)XLCustomCirclar:(UIView *)targetView{
// 繪製圓
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:targetView.bounds];
// 初始化shapeLayer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
// 設定繪製路徑
shapeLayer.path = bezierPath.CGPath;
// 將shapeLayer設定為targetview的layer的mask(遮罩)
targetView.layer.mask = shapeLayer;
}
- (void)XLCustomCirclarWithBorad:(UIView *)targetView cornerRadius:(CGFloat)cornerRadius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth{
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = CGRectMake(0, 0, targetView.frame.size.width, targetView.frame.size.height);
CAShapeLayer *borderLayer = [CAShapeLayer layer];
borderLayer.frame = CGRectMake(0, 0, targetView.frame.size.width, targetView.frame.size.height);
borderLayer.lineWidth = borderWidth;
borderLayer.strokeColor = borderColor.CGColor;
borderLayer.fillColor = [UIColor clearColor].CGColor;
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:targetView.bounds cornerRadius:cornerRadius];
maskLayer.path = bezierPath.CGPath;
borderLayer.path = bezierPath.CGPath;
[targetView.layer insertSublayer:borderLayer atIndex:0];
[targetView.layer setMask:maskLayer];
}
// 給target新增小紅點
- (void)addRedPointToTab:(UIView *)targetView{
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 10, 10)];
CAShapeLayer * shaperLayer = [CAShapeLayer layer];
shaperLayer.backgroundColor = [UIColor redColor].CGColor;
shaperLayer.path = path.CGPath;
[self addWhiteBorad:targetView bezierPath:path];
targetView.layer.mask = shaperLayer;
}
//給tabbar 新增文字 提示
- (void)addTextOfNumToTabbar:(NSString *)text targetView:(UILabel *)targetV{
targetV.backgroundColor = [UIColor redColor];
targetV.text = text;
targetV.textColor = [UIColor whiteColor];
targetV.font = [UIFont systemFontOfSize:13];
targetV.textAlignment = NSTextAlignmentCenter;
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName:targetV.font}];
targetV.frame = CGRectMake(targetV.frame.origin.x, targetV.frame.origin.y, size.width + 10, CGRectGetHeight(targetV.frame));
[self XLCustomViewAllBeadCircular:targetV cornerRadius:CGRectGetHeight(targetV.frame) / 2];
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:targetV.bounds cornerRadius:CGRectGetHeight(targetV.frame) / 2];
[self addWhiteBorad:targetV bezierPath:bezierPath];
}
// 給tabbar 新增 文字文字 提示
- (void)addTextOfStringToTabbar:(NSString *)text targetView:(UILabel *)targetV{
targetV.text = text;
targetV.textColor = [UIColor whiteColor];
targetV.font = [UIFont systemFontOfSize:10];
targetV.textAlignment = NSTextAlignmentCenter;
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName:targetV.font}];
targetV.frame = CGRectMake(targetV.frame.origin.x, targetV.frame.origin.y, size.width + 10, CGRectGetHeight(targetV.frame));
CGFloat circelR = CGRectGetHeight(targetV.frame) / 2;
// 建立貝塞爾曲線,指定繪製區域、角和角半徑
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:targetV.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomRight cornerRadii:CGSizeMake(circelR, circelR)];
// 初始化shapeLayer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
// 設定繪製路徑
shapeLayer.path = bezierPath.CGPath;
//漸變圖層
CAGradientLayer * gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(0, 0, CGRectGetWidth(targetV.frame), CGRectGetHeight(targetV.frame));
gradientLayer.startPoint = CGPointMake(0, 1);
gradientLayer.endPoint = CGPointMake(1, 0);
gradientLayer.colors = @[(__bridge id)[UIColor colorWithHex:0xFF578C].CGColor,(__bridge id)[UIColor colorWithHex:0xFF0E00].CGColor];
gradientLayer.locations = @[@(0.3f)];
CALayer * baseLayer = [CALayer layer];
[baseLayer addSublayer:gradientLayer];
[baseLayer setMask:shapeLayer];
[targetV.layer insertSublayer:baseLayer atIndex:0];
}
// 給常規控制元件新增小紅點
- (void)addRedPointCionven:(UIView *)targetView mas_makeConstraints:(void(^)(UIButton * tempV,NSNumber * helfH))block{
UIButton * rempBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(targetView.frame), CGRectGetHeight(targetView.frame))];
[targetView.superview addSubview:rempBtn];
rempBtn.tag = 7000 + targetView.tag;
UIImageView * redView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(targetView.frame) - ScaleSize(5), -ScaleSize(5), ScaleSize(10), ScaleSize(10))];
redView.backgroundColor = [UIColor redColor];
[rempBtn addSubview:redView];
[self XLCustomCirclarWithBorad:rempBtn cornerRadius:ScaleSize(10) / 2 borderColor:[UIColor whiteColor] borderWidth:2];
block(rempBtn,[NSNumber numberWithFloat:ScaleSize(10) / 2]);
}
- (void)removeRedPoint:(UIView *)targetV{
for (UIView * subView in targetV.superview.subviews) {
if (subView.tag - 7000 == targetV.tag) {
[subView removeFromSuperview];
break;
}
}
}
//給常規控制元件右上角新增純數字提示框
- (void)addTextOfNumToCionven:(UIView *)targetView textNum:(NSString *)numText mas_makeConstraints:(void(^)(UIView * tempV))block{
//建立 文字提示框
UILabel * labV = [[UILabel alloc] init];
labV.backgroundColor = [UIColor redColor];
labV.tag = 8000 + targetView.tag;
labV.text = numText;
labV.textColor = [UIColor whiteColor];
labV.font = kPingFangMedium(13);
labV.textAlignment = NSTextAlignmentCenter;
CGSize size = [numText sizeWithAttributes:@{NSFontAttributeName:labV.font}];
labV.frame = CGRectMake(0, 0, size.width + ScaleSize(10), ScaleSize(18));
[targetView.superview addSubview:labV];
block(labV);
[self XLCustomViewAllBeadCircular:labV cornerRadius:ScaleSize(9)];
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:labV.bounds cornerRadius:ScaleSize(9)];
[self addWhiteBorad:labV bezierPath:bezierPath];
}
- (void)removeNumText:(UIView *)targetV{
for (UIView * subView in targetV.superview.subviews) {
if (subView.tag - 8000 == targetV.tag) {
[subView removeFromSuperview];
break;
}
}
}
//給常規控制元件右上角新增純文字提示框
- (void)addTextOfStringToCionven:(UIView *)targetV textString:(NSString *)textStr mas_makeConstraints:(void(^)(UIButton * tempV,NSNumber * height))block{
UIButton * tempBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(targetV.frame), CGRectGetHeight(targetV.frame))];
[targetV.superview addSubview:tempBtn];
tempBtn.tag = 9000 + targetV.tag;
UILabel * titleLab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
titleLab.text = textStr;
titleLab.textColor = [UIColor whiteColor];
titleLab.font = [UIFont systemFontOfSize:10];
titleLab.textAlignment = NSTextAlignmentCenter;
[tempBtn addSubview:titleLab];
CGSize size = [textStr sizeWithAttributes:@{NSFontAttributeName:titleLab.font}];
CGFloat x = CGRectGetWidth(targetV.frame) - 5;
titleLab.frame = CGRectMake(x, -10, size.width + 10, 14);
CGFloat circelR = 7;
// 建立貝塞爾曲線,指定繪製區域、角和角半徑
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:titleLab.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomRight cornerRadii:CGSizeMake(circelR, circelR)];
// 初始化shapeLayer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
// 設定繪製路徑
shapeLayer.path = bezierPath.CGPath;
//漸變圖層
CAGradientLayer * gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(0, 0, CGRectGetWidth(titleLab.frame), CGRectGetHeight(titleLab.frame));
gradientLayer.startPoint = CGPointMake(0, 1);
gradientLayer.endPoint = CGPointMake(1, 0);
gradientLayer.colors = @[(__bridge id)[UIColor colorWithHex:0xFF578C].CGColor,(__bridge id)[UIColor colorWithHex:0xFF0E00].CGColor];
gradientLayer.locations = @[@(0.3f)];
CALayer * baseLayer = [CALayer layer];
[baseLayer addSublayer:gradientLayer];
[baseLayer setMask:shapeLayer];
[titleLab.layer insertSublayer:baseLayer atIndex:0];
block(tempBtn,[NSNumber numberWithInteger:ScaleSize(14)]);
}
- (void)removeStrText:(UIView *)targetV{
for (UIView * subView in targetV.superview.subviews) {
if (subView.tag - 9000 == targetV.tag) {
[subView removeFromSuperview];
break;
}
}
}
/** 新增白色邊框 */
- (void)addWhiteBorad:(UIView *)targetV bezierPath:(UIBezierPath *)path{
CAShapeLayer * boraderLayer = [CAShapeLayer layer];
boraderLayer.frame = CGRectMake(0, 0, targetV.bounds.size.width, targetV.bounds.size.height);
boraderLayer.lineWidth = 2;
boraderLayer.strokeColor = [UIColor whiteColor].CGColor;
boraderLayer.fillColor = [UIColor clearColor].CGColor;
boraderLayer.path = path.CGPath;
[targetV.layer insertSublayer:boraderLayer atIndex:0];
}
@end
我這裡說明一下,這些類別適合那些使用了masnory約束了的專案和控制元件
如果哪位大佬能說明一下如何及時獲取到經過masnory約束後的常規控制元件的x和y,請留言給我,萬分感謝
我的qq:2849765859 我是磊懷