轻量的顶部提示栏分类

.h 文件

//
//  NSString+LGFString.h
//  LGFOCTool
//
//  Created by apple on 2017/5/2.
//  Copyright © 2017年 来国锋. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "LGFOCTool.h"

typedef NS_ENUM(NSUInteger, lgf_TopBarMessageMode) {
    lgf_Overlay,// //视图不下移 默认
    lgf_Resize,// 视图下移 (设置此项将取消手势隐藏 LGFTopMessageView 和 LGFTopMessageView 点击事件)
};

#pragma mark - 提示view style

@interface LGFTopMessageStyle : NSObject
+ (instancetype)na;
// 提示文本
@property (copy, nonatomic) NSString *lgf_Message;
// 文本最多显示行数
@property (assign, nonatomic) NSInteger lgf_LabelMaxLine;
// 文本字体
@property (strong, nonatomic) UIFont *lgf_MessageLabelFont;
// 文本颜色
@property (strong, nonatomic) UIColor *lgf_MessageTextColor;
// 图片
@property (strong, nonatomic) UIImage *lgf_MessageIcon;
// 图片宽度
@property (assign, nonatomic) CGFloat lgf_IconWidth;
// 图片与文本与边框间距
@property (assign, nonatomic) CGFloat lgf_BetweenIconAndMessage;
// 显示滞留时间 设置 0.0 为无限 
@property (assign, nonatomic) CGFloat lgf_DimissDelay;
// 动画时间
@property (assign, nonatomic) CGFloat lgf_AnimateDuration;
// TopBar中间 label 距离顶部和底部两边边距
@property (assign, nonatomic) CGFloat lgf_TopBarSpacingHeight;
// 背景颜色
@property (strong, nonatomic) UIColor *lgf_MessageBackColor;
// 视图是否下移
@property (assign, nonatomic) lgf_TopBarMessageMode lgf_MessageMode;
@end

#pragma mark - 提示view

@interface LGFTopMessageView : UIView
@property (strong, nonatomic) LGFTopMessageStyle *style;
@property (nonatomic, strong) UIImageView *messageIcon;
@property (nonatomic, strong) UILabel *messageLabel;
// 点击回调 Block
@property (nonatomic, copy) dispatch_block_t tapHandler;
lgf_AllocOnlyOnceForH(shard);
@end

#pragma mark - 提示view UIViewController 分类结合

@interface UIViewController (LGFTopBarMessage)

/**
 展示顶部警报条
 @param style        参数设置
 @param tapHandler   点击顶部条回调 lgf_TopBarMessageMode 为 lgf_Resize 该项无效
 */
- (void)lgf_ShowTopMessageWithStyle:(LGFTopMessageStyle *)style withTapBlock:(dispatch_block_t)tapHandler;

/**
 展示顶部提示条
 @param message      提示文字
 */
- (void)lgf_ShowTopMessage:(NSString *)message;

/**
 隐藏弹出视图
 */
- (void)lgf_DismissTopMessage;

@end


.m 文件

//
//  NSString+LGFString.m
//  LGFOCTool
//
//  Created by apple on 2017/5/2.
//  Copyright © 2017年 来国锋. All rights reserved.
//

#import "UIViewController+LGFTopBarMessage.h"
#import <objc/runtime.h>

@implementation LGFTopMessageView

lgf_AllocOnlyOnceForM(LGFTopMessageView, shard);

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        self.messageLabel = [[UILabel alloc] init];
        self.messageLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        [self addSubview:self.messageLabel];
        self.messageIcon = [[UIImageView alloc] init];
        [self addSubview:self.messageIcon];
        
        // 添加轻扫手势
        UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)];
        swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
        [self addGestureRecognizer:swipeUp];
        UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)];
        swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
        [self addGestureRecognizer:swipeLeft];
        UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)];
        swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
        [self addGestureRecognizer:swipeRight];
        
        // 添加轻击手势
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapNow)];
        [self addGestureRecognizer:tap];
    }
    return self;
}

- (void)tapNow {
    // 点击了message
    [self dismiss];
    if (self.tapHandler) {
        self.tapHandler();
    }
}

- (void)dismiss {
    // 隐藏 LGFTopMessageView
    [UIView animateWithDuration:self.style.lgf_AnimateDuration animations:^{
        self.superview.transform = CGAffineTransformIdentity;
        if (self.style.lgf_MessageMode == lgf_Overlay) {
            self.lgf_y -= (self.style.lgf_TopBarSpacingHeight + self.messageLabel.lgf_height);
        }
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
}

- (void)setStyle:(LGFTopMessageStyle *)style {
    _style = style;
    [self resetViews];
}

- (void)resetViews {
    // 控件赋值
    self.messageLabel.numberOfLines = self.style.lgf_LabelMaxLine;
    self.messageLabel.text = self.style.lgf_Message;
    self.backgroundColor = self.style.lgf_MessageBackColor;
    self.messageLabel.textColor = self.style.lgf_MessageTextColor;
    self.messageIcon.image = self.style.lgf_MessageIcon;
    self.messageLabel.font = self.style.lgf_MessageLabelFont;
}

- (void)layoutSubviews {
    // 根据文字获取动态高度
    CGFloat labelWidth = self.lgf_width - (self.style.lgf_BetweenIconAndMessage * 3 + self.style.lgf_IconWidth);
    CGFloat labelHeight = MIN([self.style.lgf_Message lgf_HeightWithFont:self.style.lgf_MessageLabelFont constrainedToWidth:labelWidth], [@"" lgf_HeightWithFont:self.style.lgf_MessageLabelFont constrainedToWidth:labelWidth] * self.style.lgf_LabelMaxLine);
    if (!self.style.lgf_MessageIcon) {
        self.style.lgf_IconWidth = 0.0;
    }
    self.messageIcon.frame = CGRectMake(self.style.lgf_BetweenIconAndMessage, MAX(0, (self.lgf_height - self.style.lgf_IconWidth) / 2), self.style.lgf_IconWidth, self.style.lgf_IconWidth);
    self.messageLabel.frame = CGRectMake(self.style.lgf_IconWidth + self.style.lgf_BetweenIconAndMessage * 2, MAX(0, (self.lgf_height - labelHeight) / 2), self.lgf_width - (self.style.lgf_BetweenIconAndMessage * 3 + self.messageIcon.lgf_width), labelHeight);
}

@end

@implementation UIViewController (LGFTopBarMessage)

static char TopMessageKey;

- (void)lgf_ShowTopMessage:(NSString *)message {
    LGFTopMessageStyle *style = [LGFTopMessageStyle na];
    style.lgf_Message = message;
    [self lgf_ShowTopMessageWithStyle:style withTapBlock:nil];
}

- (void)lgf_ShowTopMessageWithStyle:(LGFTopMessageStyle *)style  withTapBlock:(dispatch_block_t)tapHandler {
    // 首先判断 self 是否已经全部加载完毕
    if ([self isViewLoaded] && self.view.window) {
        [self showMessageWithStyle:style withTapBlock:tapHandler];
    } else {
        // 如果是lgf_Overlay 因为不改变父视图位置, 所以无需等待父视图加载完毕
        if (style.lgf_MessageMode == lgf_Overlay) {
            [self showMessageWithStyle:style withTapBlock:tapHandler];
        }
        NSAssert(style.lgf_MessageMode == lgf_Overlay, @"父视图未加载完毕, 无法使用lgf_Resize ,因为lgf_Resize将改变父视图位置, 为确保父视图已经加载完毕, 请在父视图viewDidAppear方法中添加 (lgf_ShowTopMessage...)方法");
    }
}

- (void)showMessageWithStyle:(LGFTopMessageStyle *)style  withTapBlock:(dispatch_block_t)tapHandler {
    // 判断 Y 点
    CGFloat startY = 0.0;
    if (self.navigationController.navigationBar.translucent) {
        startY = 64.0;
    } else {
        startY = 0.0;
    }
    
    // 获取 label 的高度 LGFTopMessageView 的高度等于 label的高度 + lgf_topBarSpacingHeight
    CGFloat labelWidth = self.view.lgf_width - (style.lgf_BetweenIconAndMessage * 3 + style.lgf_IconWidth);
    CGFloat labelHeight = MIN([style.lgf_Message lgf_HeightWithFont:style.lgf_MessageLabelFont constrainedToWidth:labelWidth], [@"" lgf_HeightWithFont:style.lgf_MessageLabelFont constrainedToWidth:labelWidth] * style.lgf_LabelMaxLine);
    
    // 动态加载 LGFTopMessageView 防止其他视图控制器添加无用属性
    LGFTopMessageView *topMessageV = objc_getAssociatedObject(self, &TopMessageKey);
    topMessageV = [LGFTopMessageView sharedshard];
    topMessageV.frame = CGRectMake(0, startY - (style.lgf_TopBarSpacingHeight + labelHeight), CGRectGetWidth(self.view.bounds), style.lgf_TopBarSpacingHeight + labelHeight);
    objc_setAssociatedObject(self, &TopMessageKey, topMessageV, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    topMessageV.tapHandler = tapHandler;
    topMessageV.style = style;
    [self.view addSubview:topMessageV];
    
    // 隐藏之前取消延迟
    [NSObject cancelPreviousPerformRequestsWithTarget:topMessageV];
    
    // 延迟隐藏
    if (style.lgf_DimissDelay > 0) {
        [topMessageV performSelector:@selector(dismiss) withObject:nil afterDelay:style.lgf_DimissDelay + style.lgf_AnimateDuration];
    } else {
        if (style.lgf_MessageMode == lgf_Resize) {
            [topMessageV performSelector:@selector(dismiss) withObject:nil afterDelay:1.0 + style.lgf_AnimateDuration];
        }
    }
    
    // 执行显示动画
    [UIView animateWithDuration:style.lgf_AnimateDuration animations:^{
        if (style.lgf_MessageMode == lgf_Resize) {
            CGAffineTransform transform = CGAffineTransformMakeTranslation(0, style.lgf_TopBarSpacingHeight + labelHeight);
            self.view.transform = transform;
        } else {
            topMessageV.lgf_y = startY;
        }
    }];
}

- (void)lgf_DismissTopMessage {
    NSArray *subViews = self.view.subviews;
    for (UIView *subView in subViews) {
        if ([subView isKindOfClass:[LGFTopMessageView class]]) {
            LGFTopMessageView *view = (LGFTopMessageView *)subView;
            [view dismiss];
        }
    }
}

@end

@implementation LGFTopMessageStyle

- (instancetype)init {
    self = [super init];
    // 默认配置
    self.lgf_MessageBackColor = [UIColor lgf_ColorWithHexString:@"FBF9FA"];
    self.lgf_MessageTextColor = [UIColor blackColor];
    self.lgf_MessageLabelFont = [UIFont systemFontOfSize:15];
    self.lgf_MessageIcon = nil;
    self.lgf_LabelMaxLine = 1;
    self.lgf_MessageMode = lgf_Overlay;
    self.lgf_DimissDelay = 2.0;
    self.lgf_Message = @"";
    self.lgf_IconWidth = 20.0;
    self.lgf_BetweenIconAndMessage = 10.0;
    self.lgf_AnimateDuration = 0.3;
    self.lgf_TopBarSpacingHeight = 20.0;
    return self;
}

+ (instancetype)na {
    LGFTopMessageStyle *style = [[LGFTopMessageStyle alloc] init];
    return style;
}

@end

具体使用:

LGFTopMessageStyle *style = [LGFTopMessageStyle na];
    style.lgf_Message = @"来国锋发的消息息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息la的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我发的消息label发的消息lab发息我b发息我发的消息label发的消息l";
    style.lgf_MessageMode = lgf_Resize;
    style.lgf_LabelMaxLine = 4;
    style.lgf_IconWidth = 40;
    style.lgf_MessageIcon = [UIImage imageNamed:@"testIcon"];
    style.lgf_MessageLabelFont = [UIFont systemFontOfSize:15];
    [self lgf_ShowTopMessageWithStyle:style withTapBlock:^{
        NSLog(@"点击了")
    }];

附加单列宏实现

// 添加到 .h 文件
#define lgf_AllocOnlyOnceForH(methodName) + (instancetype)shared##methodName
// 添加到 .m 文件
#define lgf_AllocOnlyOnceForM(name,methodName) static name* _instance;\
+ (instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+ (instancetype)shared##methodName{\
\
return [[name alloc] init];\
}\
- (instancetype)init{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super init];\
});\
return _instance;\
}\
\
- (instancetype)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
- (instancetype)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}

效果展示:


WechatIMG1.jpeg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,463评论 25 707
  • 儿子的小伙伴这周又来了,主动要求一起画画。小伙伴要画骆驼,儿子没说不愿画骆驼,开心的一起画骆驼。画完后,小伙伴却不...
    小小培阅读 268评论 0 5
  • Ubuntu 12.0.4远程登录服务器--SSH的安装与及配置 一枚前端菜鸟之前一直使用window进行前端的开...
    Evtion阅读 224评论 0 2
  • 雨中伞 步入初中生活,步伐渐渐加快。每天起早摸黑,来去匆匆。 那天中午,天气说变就变。霎时间,雨大的像是天上的银河...
    亦荷阅读 292评论 0 0
  • 风中樱花开得香,小雨依窗痴痴望。 花似去年分外好,人却已经非姑娘。
    简村小吹阅读 233评论 17 19