UIView+RedPoint實現底部UITabBarItem和控件的右上角顯示和隱藏紅點/數字的需求

補充

前兩天有個讀者告訴我,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

普通圖片/按鈕/Label右上角顯示紅點或數字

前段時間,公司項目加入了新聞資訊功能,要求收到普通新聞在新聞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];

方法將其移除便可。

底部TabbarItem右上角顯示紅點或數字

實現這個需求的時候,我想到先前作的底部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,歡迎結交[笑臉].

相關文章
相關標籤/搜索