.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;\
}
效果展示: