美文网首页
DZNEmptyDataSet——空白数据集显示框架

DZNEmptyDataSet——空白数据集显示框架

作者: 书写不简单 | 来源:发表于2018-12-27 09:37 被阅读0次

大多数应用程序会显示内容列表、数据集(在 iOS 程序猿眼里,这里通常指的是 UITableView、UICollectionView。),但有些时候这些页面可能是空白的,特别是对于那些刚创建空账户的新用户来说。 空白界面会对用户造成不知道如何进行下一步操作的困惑,因为用户不知道屏幕空白的原因是错误/Bug、网络异常,还是用户应该自己新建内容以恢复APP的正常状态。

这个库已经被设计为不需要通过扩展(extend) UITableView 或 UICollectionView 类的方式来实现了。 使用 UITableViewController 或 UICollectionViewController 类仍然可以奏效。 只要通过遵循 DZNEmptyDataSetSource 和 DZNEmptyDataSetDelegate 协议,您将能够完全自定义应用程序的空状态的内容和外观。

遵循协议

// 遵守 DZNEmptyDataSetSource 、DZNEmptyDataSetDelegate 协议
@interface MainViewController : UITableViewController <DZNEmptyDataSetSource, DZNEmptyDataSetDelegate>

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 这里为了演示,项目中,这个应该写在请求数据失败的地方
    self.tableView.emptyDataSetSource = self;
    self.tableView.emptyDataSetDelegate = self;

    // 删除单元格分隔线的一个小技巧
    self.tableView.tableFooterView = [UIView new];
}

实现数据源协议(DZNEmptyDataSetSource)

DZNEmptyDataSetSource ——实现该协议,可以设置你想要在空白页面显示的内容,并且充分利用 NSAttributedString 功能来自定义文本外观。

  • 空白页显示图片
- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView {
    return [UIImage imageNamed:@"lion"];
}

效果图:


1.png
  • 空白页显示标题
- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView {
    NSString *title = @"QQ空间";
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont boldSystemFontOfSize:18.0f],
                                 NSForegroundColorAttributeName:[UIColor darkGrayColor]
                                 };
    return [[NSAttributedString alloc] initWithString:title attributes:attributes];
}

效果图:


2.png
  • 空白页显示详细描述
- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView{
    NSString *text = @"大家还记得自己的QQ号是几年前申请的吗";

    NSMutableParagraphStyle *paragraph = [NSMutableParagraphStyle new];
    paragraph.lineBreakMode = NSLineBreakByWordWrapping;
    paragraph.alignment = NSTextAlignmentCenter;

    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont systemFontOfSize:14.0f],
                                 NSForegroundColorAttributeName:[UIColor lightGrayColor],
                                 NSParagraphStyleAttributeName:paragraph
                                 };

    return [[NSAttributedString alloc] initWithString:text attributes:attributes];

}

效果图:


3.png
  • 空白页显示按钮:
- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state{
    // 设置按钮标题
    NSString *buttonTitle = @"点击按钮试试看";
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont boldSystemFontOfSize:17.0f]
                                 };
    return [[NSAttributedString alloc] initWithString:buttonTitle attributes:attributes];

}

// 布局:上提 170.0f
- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView {
    return -170.0f;
}

// 该方法是防止在刷新的时候,出现占位图上移的问题
- (void)emptyDataSetWillAppear:(UIScrollView *)scrollView {
    self.tableView.contentOffset = CGPointZero;
}

效果图:


4.png
  • 空白页显示按钮:按钮标题中 点击重试 四个字加粗
//
- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state{
    NSString *text = @"网络不给力,请点击重试哦~";

    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
    // 设置所有字体大小为 #15
    [attStr addAttribute:NSFontAttributeName
                   value:[UIFont systemFontOfSize:15.0]
                   range:NSMakeRange(0, text.length)];
    // 设置所有字体颜色为浅灰色
    [attStr addAttribute:NSForegroundColorAttributeName
                   value:[UIColor lightGrayColor]
                   range:NSMakeRange(0, text.length)];
    // 设置指定4个字体为蓝色
    [attStr addAttribute:NSForegroundColorAttributeName
                   value:[UIColor redColor]
                   range:NSMakeRange(7, 4)];
    return attStr;

}
// 布局:上提 170.0f
- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView {
    return -170.0f;
}
// 该方法是防止在刷新的时候,出现占位图上移的问题
- (void)emptyDataSetWillAppear:(UIScrollView *)scrollView {
    self.tableView.contentOffset = CGPointZero;
}

效果图:


4.png
  • 空白页显示按钮并添加按钮点击方法
// 空白页显示返回按钮图片
- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state {
    return [UIImage imageNamed:@"pengyouquan"];
}

- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button {
    // 可以试着返回操作
    NSLog(@"可以试着返回操作");
}

效果图:


5.png
  • 设置空白页面的背景色
- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView {
    UIColor *appleGreenColor = [UIColor colorWithRed:199/255.0 green:237/255.0 blue:204/255.0 alpha:1.0];
    return appleGreenColor;
}

  • 设置自定义视图
- (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView {
    UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [activityView startAnimating];
    return activityView;
}

效果图:(暂无)

  • 设置图片动画: 旋转 参考文章
#pragma mark - DZNEmptyDataSetSource
#pragma mark 设置空白页图片
- (nullable UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView {
    return [UIImage imageNamed:@"lion"];
}

#pragma mark 设置图片动画: 旋转
- (CAAnimation *)imageAnimationForEmptyDataSet:(UIScrollView *)scrollView {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath: @"transform"];
    
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0.0, 0.0, 1.0)];
    
    animation.duration = 0.25;
    animation.cumulative = YES;
    animation.repeatCount = MAXFLOAT;
    
    return animation;
}

#pragma mark - DZNEmptyDataSetDelegate
// 向代理请求图像视图动画权限。 默认值为NO。
// 确保从 imageAnimationForEmptyDataSet 返回有效的CAAnimation对象:
- (BOOL)emptyDataSetShouldAnimateImageView:(UIScrollView *)scrollView {
    return YES;
}

效果图:


6.gif
  • 图像视图动画:缩放
#pragma mark - DZNEmptyDataSetSource
#pragma mark 设置空白页图片
- (nullable UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView {
    return [UIImage imageNamed:@"computer"];
}

#pragma mark 设置图片动画
- (CAAnimation *)imageAnimationForEmptyDataSet:(UIScrollView *)scrollView
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
    animation.duration = 1.25;
    animation.cumulative = NO;
    animation.repeatCount = MAXFLOAT;
    animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 45, 45)];

    return animation;
}

#pragma mark - DZNEmptyDataSetDelegate
- (BOOL)emptyDataSetShouldAnimateImageView:(UIScrollView *)scrollView {
    return YES;
}

效果图:


7.gif

项目中常用的情景:

空白视图默认情况下显示一张【静态图片】,当用户点击【静态图片】以后,该图片会被替换成【加载转圈】。

简要说一下工作原理:

  • 首先在遵循协议的.m文件中声明了一个 BOOL 类型的变量,用来记录空白页面当前的加载状态:
@property (nonatomic, getter=isLoading) BOOL loading;
  • 然后为该属性设置 setter 方法,重新加载空数据集视图:
- (void)setLoading:(BOOL)loading
{
  if (self.isLoading == loading) {
      return;
  }
  _loading = loading;
  // 每次 loading 状态被修改,就刷新空白页面。
  [self.tableView reloadEmptyDataSet];
}
  • 接下来要实现几个关联协议
#pragma mark - DZNEmptyDataSetSource
#pragma mark 设置空白页图片
- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView {
    if (self.isLoading) {
        // 圆形加载图片
        return [UIImage imageNamed:@"loading_imgBlue_78x78"];
    }else {
        // 默认静态图片
        return [UIImage imageNamed:@"staticImage"];
    }
}

#pragma mark 图片旋转动画
- (CAAnimation *)imageAnimationForEmptyDataSet:(UIScrollView *)scrollView
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    animation.toValue = [NSValue valueWithCATransform3D: CATransform3DMakeRotation(M_PI_2, 0.0, 0.0, 1.0) ];
    animation.duration = 0.25;
    animation.cumulative = YES;
    animation.repeatCount = MAXFLOAT;
    
    return animation;
}

#pragma mark - DZNEmptyDataSetDelegate
#pragma mark 是否开启动画
- (BOOL)emptyDataSetShouldAnimateImageView:(UIScrollView *)scrollView {
    return self.isLoading;
}

#pragma mark 空白页面被点击时刷新页面
- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view {
    // 空白页面被点击时开启动画,reloadEmptyDataSet
    self.loading = YES;
    // 执行加载任务...
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 任务加载完成后关闭动画,reloadEmptyDataSet
        self.loading = NO;
    });
}
  • 你也可以设置所有组件彼此之间的上下间距(默认间距为11 pt)
- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView {
    return 25.0f;
}

实现代理协议 DZNEmptyDataSetDelegate

DZNEmptyDataSetDelegate ——实现该协议,可以设置你期望从空白页面返回的的行为,并接收用户交互事件。

  • 设置是否 渲染和显示空白页面(默认为YES):
- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView {
    return YES;
}
  • 设置是否 以淡入方式显示空白页面 。 (默认值为YES)
- (BOOL)emptyDataSetShouldFadeIn:(UIScrollView *)scrollView { 
    return YES;
}
  • 强制显示空数据集:当项目数量大于0时,请求代理是否仍应显示空数据集。(默认值为NO)
- (BOOL)emptyDataSetShouldBeForcedToDisplay:(UIScrollView *)scrollView;
  • 获取交互权限:是否接收用户点击事件(默认为YES):
- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView {
    // 如果正在加载中,则不响应用户交互。
    return !self.isLoading;
}
  • 获取滚动权限(默认值为NO):
- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView;
  • 获取图像动画权限:是否开启图片动画(默认值为NO):
- (BOOL)emptyDataSetShouldAnimateImageView:(UIScrollView *)scrollView {
    return YES;
}
  • 空白数据集 视图被点击 时触发该方法:
- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view {
    // 处理视图点击事件...
}
  • 空白数据集 按钮被点击时 触发该方法:
- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button {
    // 处理按钮点击事件...
}
  • 空白页将要出现
- (void)emptyDataSetWillAppear:(UIScrollView *)scrollView {
  // 如果你的空白占位图,发生偏移,可如下设置:
  self.tableView.contentOffset = CGPointZero;
}
  • 空白页已经出现
- (void)emptyDataSetDidAppear:(UIScrollView *)scrollView;
  • 空白页将要消失
- (void)emptyDataSetWillDisappear:(UIScrollView *)scrollView;
  • 空白页已经消失
- (void)emptyDataSetDidDisappear:(UIScrollView *)scrollView;

刷新布局

如果你需要刷新空白页面布局,只需调用:

[self.tableView reloadData];
// 或者
[self.collectionView reloadData];

强制布局更新

你还可以调用 [self.tableView reloadEmptyDataSet] 以使当前空白页面布局无效,并触发布局更新,绕过 -reloadData。 如果你的数据源上有很多逻辑处理,当你不需要或者想避免调用 -reloadData 时这可能很有用。 当使用 UIScrollView 时, [self.scrollView reloadEmptyDataSet] 是刷新内容的唯一方法。

相关文章

网友评论

      本文标题:DZNEmptyDataSet——空白数据集显示框架

      本文链接:https://www.haomeiwen.com/subject/cxzhlqtx.html