一、在App 开发中提示用户这样的功能非常常见。例如:用户有些不正确的操作后,App应给与相关的提示;还有在App 加载的内容的时候,为了消除用户着急的心里,我们进行一个活动指示器的提示等。。。
二、我们的提示的优点
1》使用简单,代码一行就能完成。
2》代码可以移植高,耦合度低。
3》样式随时可以修改。
4》App 提示默认经典样式。
5》提示位置可以控制。
6》支持屏幕旋转。
三、展示我们的提示效果
1、 基本的
代码调用如下:
[self.view showToastMessage:@"短信已发送,请注意查收"];
效果图如下:
2、图片
[self.view showTosatImageView:[UIImage imageNamed:@"dog.png"]];
展示效果如下:
3、图片&消息
[self.view showTosatMessage:@"看一看" title:nil image:[UIImage imageNamed:@"dog.png"]];
效果展示:[self.view showTosatMessage:@"看一看" title:@"狗狗照" image:[UIImage imageNamed:@"dog.png"]];
展示效果:[self.view showTosatMessage:@"看一看" title:@"狗狗照" image:[UIImage imageNamed:@"dog.png"] duration:2];
效果展示
[self.view showTosatMessage:@"看一看" title:@"狗狗照" image:[UIImage imageNamed:@"dog.png"] position:@"0.3" duration:2];
展示效果[self.view showActivityTaost];
效果展示:[self.view showActivityToast:@"正在加载,请稍后..." withPosition:@"0.3"];
效果展示[self.view deleteActivity];
四、提示的配置文件展示
//
// NWToastConfigurationFile.h
// ToastView
//
// Created by MAC on 2017/6/6.
// Copyright © 2017年 NetworkCode小贱. All rights reserved.
//
#ifndef NWToastConfigurationFile_h
#define NWToastConfigurationFile_h
#pragma mark 提示的样式设置
static const BOOL NWToastIsShadow = YES ;
static const BOOL NWToastIsHidesOnTap = YES ;
#pragma mark 常规变量的设置
/* 圆切角*/
static const CGFloat NWToastCornerRadius = 6.0 ;
/* 提示阴影透明度*/
static const CGFloat NWToastShadowOpacity = 0.6 ;
/* 阴影的圆角*/
static const CGFloat NWToastShadowRadius = 6.0 ;
/* 阴影的位置偏移*/
static const CGSize NWToastShadowOffset = {4.0 ,4.0} ;
/* 提示背景色透明度*/
static const CGFloat NWToastOpacity = 0.6 ;
/* 提示标题的最大换行数*/
static const NSInteger NWToastMaxTitleLines = 0 ;
/* 提示标题的字体大小*/
static const CGFloat NWToastTitleFontSize = 16.0 ;
/* 提示图片的设置*/
static const CGFloat NWToastImageViewHorizontalPadding = 10.0 ;
static const CGFloat NWToastImageViewVerticalPadding = 10.0 ;
static const CGFloat NWToastImageViewWidth = 80.0 ;
static const CGFloat NWToastImageViewHeight = 80.0 ;
/* 设置提示的最大宽度和高度*/
static const CGFloat NWToastMaxHeight = 0.8 ;
static const CGFloat NWToastMaxWidth = 0.8 ;
/* 提示内容元素上下间隔*/
static const CGFloat NWToastElementVerticalPadding = 10.0 ;
/* 提示默认位置*/
static const CGFloat NWToastVerticalCenter = 0.5 ;
/* 提示显示过程的时间*/
static const CGFloat NWToastFadeDuration = 0.3 ;
/* 提示定时器的key*/
static const NSString * NWToastTimerKey = @"NWToastTimerKey";
/* 提示存在的时间*/
static const CGFloat NWToastExistTime = 4 ;
#pragma mark 带活动指示器的设置
static const NSString * NWActivityToastKey = @"NWActivityToastKey";
/* 活动指示器的提示View的背景色灰白度的参数*/
static const CGFloat NWActivityToastComponent = 0.8 ;
/* 活动指示器的提示层的透明度*/
static const CGFloat NWActivityToastAlpha = 0.8 ;
/* 提示层的圆切角*/
static const CGFloat NWActivityToastCornerRadius = 6.0;
/* 提示是否有投影*/
static const BOOL NWActivityToastShadow = YES;
/* 提示阴影透明度*/
static const CGFloat NWActivityToastShadowOpacity = 0.6 ;
/* 阴影的圆角*/
static const CGFloat NWActivityToastShadowRadius = 6.0 ;
/* 阴影的位置偏移*/
static const CGSize NWActivityToastShadowOffset = {4.0 ,4.0} ;
/* 提示消息文字大小*/
static const CGFloat NWActivityToastFont = 16.0 ;
/* 提示消息文字的最大展示行*/
static const NSInteger NWActivityMaxLine = 0 ;
/* 提示文字最大展示的宽度*/
static const CGFloat NWActivityMaxWidth = 0.6;
/* 提示文字最大展示的高度*/
static const CGFloat NWActivityMaxHeigth = 0.6;
/* 提示内容元素上下间隔*/
static const CGFloat NWActivityToastElementVerticalPadding = 10.0 ;
/* 活动指示器的宽与高*/
static const CGFloat NWActivityToastWidth = 60.0 ;
static const CGFloat NWActivityToastHeight = 60.0 ;
/* 活动指示器移除的时间*/
static const CGFloat NWActivityToastFadeDuration = 0.3 ;
#endif /* NWToastConfigurationFile_h */
五、提示方法展示
//
// UIView+NWToast.h
// ToastView
//
// Created by MAC on 2017/6/6.
// Copyright © 2017年 NetworkCode小贱. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (NWToast)
/*!
单独的一个信息展示
*/
-(void)showToastMessage:(NSString*)message;
/*!
单独显示图片
*/
-(void)showTosatImageView:(UIImage*) image;
/*!
标题、图片、消息
*/
-(void)showTosatMessage:(NSString*)message title:(NSString*)title image:(UIImage*) image ;
/*!
标题、图片、消息、时间
*/
-(void)showTosatMessage:(NSString*)message title:(NSString*)title image:(UIImage*) image duration:(NSTimeInterval)time;
/*!
标题、图片、消息、位置
point : 高度小于提示框的一半,则为默认状态
*/
-(void)showTosatMessage:(NSString*)message title:(NSString*)title image:(UIImage*) image position:(id) point duration:(NSTimeInterval)time;
#pragma mark 带有活动指示器的提示
/**
单独的活动指示器
*/
-(void)showActivityTaost;
/**
活动指示器和文字和位置
*/
-(void)showActivityToast:(NSString*)message withPosition:(id) point;
/**
清楚活动指示器
*/
-(void)deleteActivity;
@end
//
// UIView+NWToast.m
// ToastView
//
// Created by MAC on 2017/6/6.
// Copyright © 2017年 NetworkCode小贱. All rights reserved.
//
#import "UIView+NWToast.h"
#import "NWToastConfigurationFile.h"
#import <objc/runtime.h>
@implementation UIView (NWToast)
#pragma mark showToastMessage:
-(void)showToastMessage:(NSString*)message{
UIView * tosat = [self createTosast:message title:nil image:nil];
[self nwShowTosat:tosat duration:NWToastExistTime position:nil];
}
#pragma mark showTosatImageView:
-(void)showTosatImageView:(UIImage*) image{
UIView * tosat = [self createTosast:nil title:nil image:image];
[self nwShowTosat:tosat duration:NWToastExistTime position:nil];
}
#pragma mark showTosatMessage:title:image
-(void)showTosatMessage:(NSString*)message title:(NSString*)title image:(UIImage*) image {
UIView * tosat = [self createTosast:message title:title image:image];
[self nwShowTosat:tosat duration:NWToastExistTime position:nil];
}
#pragma mark showTosatMessage:title:image:duration
-(void)showTosatMessage:(NSString*)message title:(NSString*)title image:(UIImage*) image duration:(NSTimeInterval)time{
UIView * tosat = [self createTosast:message title:title image:image];
[self nwShowTosat:tosat duration:time position:nil];
}
#pragma mark showTosatMessage:title:image:position
-(void)showTosatMessage:(NSString*)message title:(NSString*)title image:(UIImage*) image position:(id) point duration:(NSTimeInterval)time {
UIView * tosat = [self createTosast:message title:title image:image];
[self nwShowTosat:tosat duration:time position:point];
}
#pragma mark toast展示到视图上
-(void)nwShowTosat:(UIView*)toast duration:(NSTimeInterval)time position:(id) point {
/**
设置提示的位置
*/
toast.center = [self nwCalculateTosat:toast withPosition:point];
toast.alpha = 0.0;
/**
添加点击事件
*/
if (NWToastIsHidesOnTap) {
toast.userInteractionEnabled = YES;
UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:toast action:@selector(tapClick:)];
[toast addGestureRecognizer:tapGestureRecognizer];
/**
让手势事件独立性
就是一个时间不处理完,就不响应下一个事件
*/
toast.exclusiveTouch = YES;
}
/**
渲染
*/
[self addSubview:toast];
/**
添加动画
*/
[UIView animateWithDuration:NWToastFadeDuration delay:0.0 options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction) animations:^{
toast.alpha = 1.0;
} completion:^(BOOL finished) {
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(toastTimerDidFinish:) userInfo:toast repeats:NO];
/**
动态注册标记
*/
objc_setAssociatedObject(toast, &NWToastTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}];
}
#pragma mark toastTimerDidFinish
-(void)toastTimerDidFinish:(NSTimer*)timer{
/**
隐藏提示
*/
[self nwHiddenToast:timer.userInfo];
}
#pragma mark tapClick
-(void)tapClick:(UIGestureRecognizer*)recognizer{
/**
获取现有的定时器,并清除
*/
NSTimer * timer = (NSTimer*) objc_getAssociatedObject(self, &NWToastTimerKey);
[timer invalidate];
/**
隐藏提示
*/
[self nwHiddenToast:recognizer.view];
}
/*!
隐藏提示
*/
-(void)nwHiddenToast:(UIView*)toast{
[UIView animateWithDuration:NWToastFadeDuration delay:0.0 options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) animations:^{
toast.alpha = 0.0;
} completion:^(BOOL finished) {
[toast removeFromSuperview];
CFBridgingRetain(toast);
}];
}
#pragma mark 计算tosat 的center
-(CGPoint)nwCalculateTosat:(UIView*)tosat withPosition:(id) point {
if ([point isKindOfClass:[NSString class]]) {
CGFloat value = self.bounds.size.height * [point floatValue];
if (value>tosat.bounds.size.height * 0.5) {
return CGPointMake(self.center.x, value);
}
}
CGFloat value = self.bounds.size.height * NWToastVerticalCenter;
return CGPointMake(self.center.x, value);
}
#pragma mark 根据传入的数据创建Tosat的大小
-(UIView*)createTosast:(NSString*)message title:(NSString*)title image:(UIImage*)image{
/**
排除对象全部不存在的情况
*/
if ((message == nil)&&(title == nil)&&(image == nil)) {
return nil;
}
/**
创建三个对象
*/
UILabel * nwMessageLable = nil;
UILabel * nwTitleLable = nil;
UIImageView * nwImageView = nil;
/**
创建一个要展示的对象
*/
UIView * nwToastView = [UIView new];
/* 自动布局*/
nwToastView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleBottomMargin );
/* 切角*/
nwToastView.layer.masksToBounds = YES;
nwToastView.layer.cornerRadius = NWToastCornerRadius;
/* 是否设置阴影 */
if (NWToastIsShadow) {
/* 颜色*/
nwToastView.layer.shadowColor = [UIColor blackColor].CGColor;
/* 透明度*/
nwToastView.layer.shadowOpacity = NWToastShadowOpacity ;
/* 阴影的圆角*/
nwToastView.layer.shadowRadius = NWToastShadowRadius;
/* 阴影的位置偏移*/
nwToastView.layer.shadowOffset = NWToastShadowOffset;
}
/**
设置其背景色
*/
nwToastView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:NWToastOpacity];
/**
监测标题是否存在
*/
/**
检测是否有标题
*/
if (title != nil) {
nwTitleLable = [UILabel new];
/* 设置文本可折叠的行数*/
nwTitleLable.numberOfLines = NWToastMaxTitleLines ;
/* 设置文本字体的大小*/
nwTitleLable.font = [UIFont boldSystemFontOfSize:NWToastTitleFontSize];
/* 显示的样式*/
nwTitleLable.textAlignment = NSTextAlignmentCenter;
nwTitleLable.lineBreakMode = NSLineBreakByWordWrapping;
/* 设置字体颜色和背景颜色*/
nwTitleLable.textColor = [UIColor whiteColor];
nwTitleLable.backgroundColor = [UIColor clearColor];
/* 标签的透明度*/
nwTitleLable.alpha = 1.0;
/* 内容设置*/
nwTitleLable.text = title ;
/**
计算标题最大的展示范围
*/
CGSize titleMaxSize = CGSizeMake(self.bounds.size.width*NWToastMaxWidth -20, self.bounds.size.height* NWToastMaxHeight - 2 * NWToastElementVerticalPadding);
/**
获取标题的实际Size
*/
CGSize realSize = [self sizeForString:title fontSize:nwTitleLable.font constrainedSize:titleMaxSize lineBreakMode:nwTitleLable.lineBreakMode];
nwTitleLable.frame = CGRectMake(0, NWToastElementVerticalPadding, realSize.width, realSize.height);
nwTitleLable.center = CGPointMake(nwToastView.center.x, nwTitleLable.center.y);
[nwToastView addSubview:nwTitleLable];
}
/**
创建一个对象
*/
CGFloat titleRealHeight = NWToastElementVerticalPadding;
CGFloat titleRealWidth = 0.0;
if (nwTitleLable) {
titleRealHeight = NWToastElementVerticalPadding * 2 + nwTitleLable.bounds.size.height;
titleRealWidth = NWToastElementVerticalPadding * 2 + nwTitleLable.bounds.size.width;
}
if (image != nil) {
nwImageView = [[UIImageView alloc]initWithImage:image];
/* 图片展示的类型*/
nwImageView.contentMode = UIViewContentModeScaleAspectFit;
/* 设置图片容器的大小*/
nwImageView.frame = CGRectMake(NWToastImageViewHorizontalPadding, titleRealHeight, NWToastImageViewWidth, NWToastImageViewHeight);
[nwToastView addSubview:nwImageView];
}
if (image) {
titleRealHeight = NWToastElementVerticalPadding + NWToastImageViewHeight + titleRealHeight;
}
/**
判断是否有消息
*/
if (message != nil) {
nwMessageLable = [UILabel new];
/* 设置文本可折叠的行数*/
nwMessageLable.numberOfLines = NWToastMaxTitleLines ;
/* 设置文本字体的大小*/
nwMessageLable.font = [UIFont systemFontOfSize:NWToastTitleFontSize];
/* 显示的样式*/
nwMessageLable.textAlignment = NSTextAlignmentCenter;
nwMessageLable.lineBreakMode = NSLineBreakByWordWrapping;
/* 设置字体颜色和背景颜色*/
nwMessageLable.textColor = [UIColor whiteColor];
nwMessageLable.backgroundColor = [UIColor clearColor];
/* 标签的透明度*/
nwMessageLable.alpha = 1.0;
/* 内容设置*/
nwMessageLable.text = message ;
/**
计算标题最大的展示范围
*/
CGSize messageMaxSize = CGSizeMake(self.bounds.size.width*NWToastMaxWidth -20, self.bounds.size.height* NWToastMaxHeight - 2 * NWToastElementVerticalPadding);
/**
获取标题的实际Size
*/
CGSize realSize = [self sizeForString:message fontSize:nwMessageLable.font constrainedSize:messageMaxSize lineBreakMode:nwMessageLable.lineBreakMode];
nwMessageLable.frame = CGRectMake(0, titleRealHeight, realSize.width, realSize.height);
[nwToastView addSubview:nwMessageLable];
}
/**
创建一个对象
*/
CGFloat messagerealWidth = 0.0;
if (nwMessageLable) {
titleRealHeight = titleRealHeight + NWToastElementVerticalPadding + nwMessageLable.bounds.size.height;
messagerealWidth = NWToastElementVerticalPadding * 2 + nwMessageLable.bounds.size.width;
}
/**
比较大小
*/
CGFloat maxWidth = MAX(titleRealWidth, messagerealWidth);
if (maxWidth<NWToastImageViewWidth) {
maxWidth = NWToastImageViewWidth + 2 * NWToastElementVerticalPadding;
}
nwToastView.frame = CGRectMake(0, 0, maxWidth, titleRealHeight);
if (nwMessageLable) {
nwMessageLable.center = CGPointMake(nwToastView.center.x, nwMessageLable.center.y);
}
if (nwImageView) {
nwImageView.center = CGPointMake(nwToastView.center.x, nwImageView.center.y);
}
if (nwTitleLable) {
nwTitleLable.center = CGPointMake(nwToastView.center.x, nwTitleLable.center.y);
}
return nwToastView;
}
#pragma mark 计算文字宽高的函数
-(CGSize)sizeForString:(NSString*)string fontSize:(UIFont*)font constrainedSize:(CGSize)constrainedSize lineBreakMode:(NSLineBreakMode)lineBreakMode{
/**
判断方法是否可以相应
注意这里我们不做判断了,因为现在的App系统都在8.0以上
*/
NSMutableParagraphStyle * nwParagraphStyle = [NSMutableParagraphStyle new];
nwParagraphStyle.lineBreakMode = lineBreakMode;
NSDictionary * attributes = @{NSFontAttributeName:font,NSParagraphStyleAttributeName:nwParagraphStyle};
CGRect realRect = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
return realRect.size;
}
#pragma mark 带活动指示器的提示
#pragma mark 单独的活动指示器提示
-(void)showActivityTaost{
[self showActivityToast:nil withPosition:nil];
}
#pragma mark 带文字和活动指示器的提示
-(void)showActivityToast:(NSString*)message withPosition:(id) point{
/**
先检测,当前视图上是否有正在进行的Toast
*/
UIView * ExistActivityToast = (UIView*) objc_getAssociatedObject(self, &NWActivityToastKey);
if (ExistActivityToast) {
return;
}
/**
创建一个展示View
*/
UIView * activityToast = [UIView new];
/**
设置提示的背景色
*/
activityToast.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:NWActivityToastComponent];
/**
设置提示元素的自动适应
*/
activityToast.autoresizingMask = (UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin);
/**
设置提示层的透明度
*/
activityToast.alpha = NWActivityToastAlpha ;
/**
提示层的圆切角
*/
activityToast.layer.masksToBounds = YES;
activityToast.layer.cornerRadius = NWActivityToastCornerRadius;
/**
是否有投影
*/
if (NWActivityToastShadow) {
activityToast.layer.shadowColor = [UIColor blackColor].CGColor;
activityToast.layer.shadowOpacity = NWActivityToastShadowOpacity;
activityToast.layer.shadowRadius = NWActivityToastShadowRadius;
activityToast.layer.shadowOffset = NWActivityToastShadowOffset;
}
/**
活动指示器的创建
样式
UIActivityIndicatorViewStyleWhiteLarge
UIActivityIndicatorViewStyleWhite
UIActivityIndicatorViewStyleGray
*/
UIActivityIndicatorView * ActivityView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
/**
设置大小
*/
ActivityView.frame = CGRectMake(0, NWActivityToastElementVerticalPadding, NWActivityToastWidth, NWActivityToastHeight);
/**
添加并开始运动
*/
[activityToast addSubview:ActivityView];
[ActivityView startAnimating];
/**
判断是否有提示文字
*/
UILabel * nWMessageLable = nil ;
if (message) {
nWMessageLable = [[UILabel alloc]init];
nWMessageLable.font = [UIFont systemFontOfSize:NWActivityToastFont];
nWMessageLable.numberOfLines = NWActivityMaxLine;
/**
显示样式
*/
nWMessageLable.lineBreakMode = NSLineBreakByWordWrapping;
nWMessageLable.textAlignment = NSTextAlignmentCenter;
/**
设置颜色
*/
nWMessageLable.textColor = [UIColor whiteColor];
nWMessageLable.backgroundColor = [UIColor clearColor];
/**
透明度
*/
nWMessageLable.alpha = 1.0 ;
/**
设置文字
*/
nWMessageLable.text = message;
/**
获取文字最大展示的Size
*/
CGSize maxSize = CGSizeMake(self.bounds.size.width * NWActivityMaxWidth -20 , self.bounds.size.height * NWActivityMaxHeigth - 2 * NWActivityToastElementVerticalPadding);
/**
获取文字的真实大小
*/
CGSize realSize = [self sizeForString:message fontSize:nWMessageLable.font constrainedSize:maxSize lineBreakMode:nWMessageLable.lineBreakMode];
nWMessageLable.frame = CGRectMake(0, CGRectGetMaxY(ActivityView.frame) +NWActivityToastElementVerticalPadding , realSize.width, realSize.height);
[activityToast addSubview:nWMessageLable];
}
/**
给活动指示器提示层动态添加标记
*/
objc_setAssociatedObject(self, &NWActivityToastKey, activityToast, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
/**
创建一个对象
*/
CGFloat messageWidth = 0.0 ;
CGFloat messageHeight = 0.0;
if (nWMessageLable) {
messageWidth = nWMessageLable.bounds.size.width + 2 * NWActivityToastElementVerticalPadding;
messageHeight = nWMessageLable.bounds.size.height + NWActivityToastElementVerticalPadding;
}
/**
设置活动器的大小
*/
activityToast.frame = CGRectMake(0, 0, MAX(messageWidth, NWActivityToastWidth + 2* NWActivityToastElementVerticalPadding), 2 * NWActivityToastElementVerticalPadding + NWActivityToastHeight + messageHeight);
/**
设置各个元素的位置
*/
ActivityView.center = CGPointMake(activityToast.center.x, ActivityView.center.y);
if (nWMessageLable) {
nWMessageLable.center = CGPointMake(activityToast.center.x, nWMessageLable.center.y);
}
/**
设置提示器的位置
*/
if (point) {
if ([point isKindOfClass:[NSString class]]) {
CGFloat valuePoint = self.bounds.size.height * [point floatValue];
if (valuePoint < activityToast.bounds.size.height * 0.5) {
activityToast.center = CGPointMake(self.center.x, self.bounds.size.height * 0.5);
}else{
activityToast.center = CGPointMake(self.center.x, valuePoint);
}
}
}else{
activityToast.center = CGPointMake(self.center.x, self.bounds.size.height * 0.5);
}
[self addSubview:activityToast];
}
#pragma mark 清楚活动指示器
-(void)deleteActivity
{
/**
检测当前控制是否有指示器存在
*/
UIView * activityView = objc_getAssociatedObject(self, &NWActivityToastKey);
if (activityView) {
[UIView animateWithDuration:NWActivityToastFadeDuration delay:0.0 options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) animations:^{
activityView.alpha = 0.0;
} completion:^(BOOL finished) {
/**
移除视图
*/
[activityView removeFromSuperview];
CFBridgingRetain(activityView);
/**
移除标记
*/
objc_setAssociatedObject(self, &NWActivityToastKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}];
}
}
@end