一、介绍
在app中使用刷新控件或者第三方刷新库是最常见的功能,在请求服务器时,获取数据的过程是处于不可见状态的,那么通过这个刷新状态可以给用户以直观的感受,这是增强用户体验的一个相当好的方法。我个人认为,有时这个方法仍有不足,就是当拉取到数据时,用户只是知道数据有了,并没有直接告知用户拉取了或者刷新了多少条数据。所以,这里我写了一个类似于网易云音乐的“朋友”模块中的一个刷新条目显示弹框。
二、思想
1、创建一个messageView,内部包含一个label,使用masonry约束,将其放到navigationBar后面,默认状态是透明的;
2、navigationBar可以是系统的,也可以是自定义的,根据需求去应用;
3、刷新结束时通过UIView的block动画改编透明度并显示,显示一定时间后自动显示隐藏;
4、创建的实例都放在基类中进行,暴露给子类去调用即可;
三、代码
ShowMessageView.h
// // ShowMessageView.h // ShowMessageTest // // Created by 夏远全 on 2018/3/22. // Copyright ? 2018年 夏远全. All rights reserved. // #import <UIKit/UIKit.h> @interface ShowMessageView : UIView //创建显示弹框(这个直接放在基类中创建,并将该实例对象暴露给子类使用,vc的系统导航栏没有隐藏掉) +(instancetype)createShowMessageViewInViewController:(UIViewController *)vc; //创建显示弹框(这个直接放在基类中创建,并将该实例对象暴露给子类使用,vc的系统导航栏被隐藏掉了,传入vc自定义的导航栏customNav) +(instancetype)createShowMessageViewInViewController:(UIViewController *)vc customNav:(UIView *)customNav; //显示消息 (刷新结束后调用) -(void)showMessage:(NSString *)message; //隐藏消息 (需要在基类的viewWillDisappear调用一次就行了) -(void)hideMessage; @end
ShowMessageView.m
// // ShowMessageView.m // ShowMessageTest // // Created by 夏远全 on 2018/3/22. // Copyright ? 2018年 夏远全. All rights reserved. // #import "ShowMessageView.h" #import <Masonry.h> #define isIphoneX_YML (kScreenWidth == 375.0 && kScreenHeight == 812.0) //没有横屏模式才能这么判断 #define kStatusBarHeight (isIphoneX_YML ? 44.0 : 20.0) #define kNavigationHeight 44.0 #define kNavigationAndStatusBarHeight (kStatusBarHeight + kNavigationHeight) @interface ShowMessageView () @property (nonatomic, strong) UILabel *messageLabel; @property (nonatomic, assign) CGFloat messsageWidth; @end @implementation ShowMessageView #pragma mark - life cycle +(instancetype)createShowMessageViewInViewController:(UIViewController *)vc { ShowMessageView *messageView = [[self alloc] initWithFrame:CGRectMake(0, kNavigationAndStatusBarHeight-40, 200, 40)]; messageView.backgroundColor = [UIColor clearColor]; messageView.alpha = 0; messageView.hidden = YES; messageView.centerX = vc.navigationController.navigationBar.centerX; [messageView setShadowForView:messageView]; [vc.navigationController.navigationBar addSubview:messageView]; [vc.navigationController.navigationBar sendSubviewToBack:messageView]; [messageView setup]; return messageView; } +(instancetype)createShowMessageViewInViewController:(UIViewController *)vc customNav:(UIView *)customNav;{ ShowMessageView *messageView = [[self alloc] initWithFrame:CGRectMake(0, kNavigationAndStatusBarHeight-40, 200, 40)]; messageView.backgroundColor = [UIColor clearColor]; messageView.alpha = 0; messageView.hidden = YES; messageView.centerX = customNav.centerX; [ShadowUtility setShadowForView:messageView]; [customNav addSubview:messageView]; [customNav sendSubviewToBack:messageView]; [messageView setup]; return messageView; } -(void)setup { [self setDefalut]; [self addSubViews]; [self setupSubviewsConstraints]; } -(void)setDefalut { } #pragma mark - add subViews -(void)addSubViews { [self addSubview:self.messageLabel]; } #pragma mark - layout subviews -(void)setupSubviewsConstraints { [self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.mas_centerX); make.centerY.equalTo(self.mas_centerY); make.height.equalTo(self.mas_height); if (self.messsageWidth > 0) { make.width.equalTo(@(MAX(100, self.messsageWidth)+20)); } }]; } #pragma mark - event response #pragma mark - public methods -(void)showMessage:(NSString *)message{ self.messageLabel.text = message; if (message.length > 0) { self.messsageWidth = [message boundingRectWithSize:CGSizeMake(MAXFLOAT, 40) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size.width; [self setupSubviewsConstraints]; } if (self.alpha == 0) { self.hidden = NO; [UIView animateWithDuration:0.8 animations:^{ self.alpha = 1.0; self.transform = CGAffineTransformMakeTranslation(0,40+10); } completion:^(BOOL finished) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [UIView animateWithDuration:0.3 animations:^{ self.alpha = 0; } completion:^(BOOL finished) { self.hidden = YES; self.transform = CGAffineTransformIdentity; }]; }); }]; } } -(void)hideMessage{ self.alpha = 0; self.transform = CGAffineTransformIdentity; } #pragma mark - private methods - (void)setShadowForView:(UIView *)view { view.layer.shadowColor = HEXCOLOR(0xaeaeae).CGColor; view.layer.shadowOffset = CGSizeMake(0, 0); view.layer.shadowRadius = 4.0; view.layer.shadowOpacity = 0.2; view.layer.shouldRasterize = YES; view.layer.rasterizationScale = [UIScreen mainScreen].scale; } #pragma mark - getters and setters -(UILabel *)messageLabel{ if (!_messageLabel) { _messageLabel = [[UILabel alloc] init]; _messageLabel.layer.cornerRadius = 20; _messageLabel.layer.masksToBounds = YES; _messageLabel.font = [UIFont systemFontOfSize:16]; _messageLabel.textAlignment = NSTextAlignmentCenter; _messageLabel.textColor = [UIColor whiteColor]; _messageLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; } return _messageLabel; } @end
四、使用
1、在基类创建
@property (nonatomic, strong) ShowMessageView *showMessageView; //在基类中定义实例属性
self.showMessageView = [ShowMessageView createShowMessageViewInViewController:self]; //在基类中创建实例
2、在基类实现必要的方法
- (void)viewWillDisappear:(BOOL)animated //在基类中调用必要的方法 { [super viewWillDisappear:animated]; [self.showMessageView hideMessage]; }
3、子类调用
[weakSelf.tableView.mj_header endRefreshing]; [weakSelf.showMessageView showMessage:@"刷新了20条新数据"]; //结束刷新后显示条目弹框
五、效果