1. 程式人生 > >新增小紅點給Tabbar或UIview右上角、文字文字、數字文字 、切圓角

新增小紅點給Tabbar或UIview右上角、文字文字、數字文字 、切圓角

這兩天在搞給tabbar或常規控制元件新增小圓點、數字文字、純文字的需求。使用了Masnory這個庫對常規控制元件新增約束有一個巨大的坑,就是無法及時獲取到常規控制元件的x和y。但是可以及時獲取到常規控制元件的w和h。
這就導致瞭如果使用masnory約束之後的控制元件,無法把什麼紅點、文字文字、數字文字直接作為子檢視新增到目標控制元件上,列位看官請耐心的看下去。
如果是常規控制元件的常規操作的話是可以把小紅點作為子檢視直接新增到目標空間上的,但是在iOS開發中我們經常會遇到常規控制元件有切圓角等一些操作,尤其是不規則圓角,那麼我們使用了UIBezierPath和CAShaperlayer結合的方式對目標控制元件做了切圓角操作。這就使得目標控制元件的layer層經過了.mask的操作,對layer層進行了切割,使得目標控制元件的右上角無法渲染任何子檢視。故而我這裡無法將之作為子檢視直接新增到目標控制元件上。
於是我們換一個思路,生成一個與目標控制元件同樣大小的view,新增到目標控制元件的父檢視上,把目標控制元件蓋起來,然後,再把小紅點什麼的新增到新生成的view上。
先來看看效果:tabbar上新增


常規控制元件新增

我在這裡封裝了兩個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 我是磊懷