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

                            ??????
      以下内容来源于官方源码、 README 文档、测试 Demo 以及个人使用总结 !

[TOC]

DZNEmptyDataSet

DZNEmptyDataSet 是基于 UITableViewUICollectionView 的范畴/扩展(category)类,它可以在空白页面上显示提示信息。

这是 iOS 内建的标准,用于处理空表和集合视图。默认情况下,如果你的表视图是空的,屏幕上什么也不会显示,它给用户的体验不是很好。

使用这个库,你只需要实现一些协议,iOS 就会很好地处理集合视图,然后合理美观地显示出用户信息。

支付宝-查询我的挂号记录

其他效果图参考

使用该框架的项目

将你的项目添加到列表中 并且提供一张(320px)的效果图。

空数据设计模式(The Empty Data Set Pattern)

也被称为 Empty state 或者 Blank Slate

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

请阅读这篇非常有趣的文章 Designing For The Empty States

iOS 9人机界面指南 1.4.2 中也提及过类似的指引:

如果应用中所有的功能当前都不可用,那么应该显示一些内容来解释当前的情形,并建议用户如何进行后续操作。这部分内容给予了用户以反馈,使用户相信你的应用现在没问题。同时这也可以稳定用户情绪,让他们决定是否要采取纠正措施,继续使用应用,还是切换到另一个应用。

Empty Data Sets 有助于:

  • 避免使用空白屏幕,并向用户传达屏幕空白的原因。
  • 用户指引(特别是作为引导页面)。
  • 避免其他中断机制,如显示错误警报。
  • 一致性和改善用户体验。
  • 传递品牌价值。

特性

  • 兼容 UITableViewUICollectionView 。 也兼容 UISearchDisplayControllerUIScrollView
  • 通过显示图片、标题、详细文本、按钮,提供布局外观的多种可能性。
  • 使用 NSAttributedString 类提供更容易定制的外观。
  • 使用 Auto Layout 以自动将内容集中到表格视图,并支持自动旋转。 也接受自定义垂直和水平对齐。
  • 自定义背景颜色。
  • 允许在整个表格矩形上轻敲手势(有助于放弃第一个响应者或类似操作)。
  • 提供更高级的定制,允许自定义视图。
  • 兼容 Storyboard
  • 兼容iOS 6,tvOS 9或更高版本。
  • 兼容iPhone,iPad和Apple TV。
  • 支持 App Store 。

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

安装

支持 CocoaPods 导入

pod ‘DZNEmptyDataSet‘

使用

完整文档参考:CocoaPods 自动生成文档

导入

#import "UIScrollView+EmptyDataSet.h"

作为框架导入:

#import <DZNEmptyDataSet/UIScrollView+EmptyDataSet.h>

遵循协议

// 遵守 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 ——实现该协议,可以设置你想要在空白页面显示的内容,并且充分利用 NSAttributedString 功能来自定义文本外观。

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

效果图:


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

效果图:


  • 空白页显示详细描述
- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView {
    NSString *text = @"你好,我的名字叫辛巴,大草原是我的家!";

    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];
}

效果图:


  • 空白页显示按钮:示例1
- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state {
    // 设置按钮标题
    NSString *buttonTitle = @"喜欢我就点点点点我";
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont boldSystemFontOfSize:17.0f]
                                 };
    return [[NSAttributedString alloc] initWithString:buttonTitle attributes:attributes];
}

效果图:

  • 空白页显示按钮:示例2

按钮点击高亮效果

- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state {
    NSString *text = @"Learn more";
    UIFont   *font = [UIFont systemFontOfSize:15.0];
    // 设置默认状态、点击高亮状态下的按钮字体颜色
    UIColor  *textColor = [UIColor colorWithHex:(state == UIControlStateNormal) ? @"007ee5" : @"48a1ea"];

    NSMutableDictionary *attributes = [NSMutableDictionary new];
    [attributes setObject:font      forKey:NSFontAttributeName];
    [attributes setObject:textColor forKey:NSForegroundColorAttributeName];

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

效果图:

  • 空白页显示按钮:示例3

按钮标题中 点击重试 四个字加粗:

#pragma mark - DZNEmptyDataSetSource

- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView {
    return [UIImage imageNamed:@"placeholder_No_Network"];
}

- (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:HexColor(@"#007EE5")
                   range:NSMakeRange(7, 4)];
    return attStr;
}

- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView {
    return -70.0f;
}

#pragma mark - DZNEmptyDataSetDelegate

- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button {
    // button clicked...
}

- (void)emptyDataSetWillAppear:(UIScrollView *)scrollView {
    self.tableView.contentOffset = CGPointZero;
}

效果图

  • 空白页显示按钮:示例4
// 空白页显示返回按钮图片
- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state {
    return [UIImage imageNamed:@"placeholder_return"];
}

- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button {
    [self.navigationController popViewControllerAnimated:YES];
}

  • 设置按钮的背景颜色
- (nullable UIImage *)buttonBackgroundImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state;

  • 设置按钮图片
- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state {
    return [UIImage imageNamed:@"Image"];
}

效果图:


  • 设置图片的 tintColor
- (UIColor *)imageTintColorForEmptyDataSet:(UIScrollView *)scrollView {
    return [UIColor yellowColor];
}

效果图:就是设置图片颜色,脑补中。。。


  • 设置空白页面的背景色
- (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;
}

效果图:

  • 图像视图动画:缩放
#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;
}

效果图:


  • 我们发现在官方的 Applications Demo 应用中的空白视图中的动画是这样的:

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

通过阅读源码,可以发现它是这样工作的:

  1. 首先在遵循协议的.m文件中声明了一个 BOOL 类型的变量,用来记录空白页面当前的加载状态:
@property (nonatomic, getter=isLoading) BOOL loading;
  1. 然后为该属性设置 setter 方法,重新加载空数据集视图:
- (void)setLoading:(BOOL)loading
{
  if (self.isLoading == loading) {
      return;
  }

  _loading = loading;
  // 每次 loading 状态被修改,就刷新空白页面。
  [self.tableView reloadEmptyDataSet];
}
  1. 接下来要实现几个关联协议

    #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;
        });
    }
    

  • 此外,你还可以调整内容视图的垂直对齐(垂直偏移量)方式:
// 向上偏移量为表头视图高度/2
- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView {
    return -self.tableView.tableHeaderView.frame.size.height/2.0f;
}
// 或者,返回固定值
- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView {
    return -64;
}

效果图:


  • 最后,你也可以设置所有组件彼此之间的上下间距(默认间距为11 pt):
- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView {
    return 25.0f;
}

效果图:


实现代理协议

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] 是刷新内容的唯一方法。

参考文章

作者:独木舟的木
链接:https://www.jianshu.com/p/f70dc3e0f436
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

原文地址:https://www.cnblogs.com/dalianmengzi/p/9860909.html

时间: 2024-10-12 02:09:48

DZNEmptyDataSet——空白数据集显示框架的相关文章

功能强大的 iOS 富文本编辑与显示框架:YYText

功能强大的 iOS 富文本编辑与显示框架.(该项目是 YYKit 组件之一) 特性 API 兼容 UILabel 和 UITextView 支持高性能的异步排版和渲染 扩展了 CoreText 的属性以支持更多文字效果 支持 UIImage.UIView.CALayer 作为图文混排元素 支持添加自定义样式的.可点击的文本高亮范围 支持自定义文本解析 (内置简单的 Markdown/表情解析) 支持文本容器路径.内部留空路径的控制 支持文字竖排版,可用于编辑和显示中日韩文本 支持图片和富文本的复

excel2013 打开为灰色空白 左下角显示就绪 要把文件拖进去才能打开!

最近电脑excel2013 打开总是为灰色空白 左下角显示就绪 要把文件拖进去或者在此再打开一个才能打开! 在网上搜了一下,我是使用下面这个方法解决的: 步骤一:请您在“开始”菜单的搜索框中输入“regedit”并按回车,如果弹出用户账户控制窗口,请点击“继续”.在左半边页面右击“计算机”,选择“导出”,然后将其保存与桌面上.这是我们备份下来的注册表,如果我们在操作中发生什么错误的话,我们可以双击导入来恢复成原来的注册表. 步骤二:1. 依次点击开始,在搜索框中输入regedit,打开注册表编辑

织梦dedecms出现系统基本参数空白或显示Call to undefined function make_hash()

织梦dedecms出现系统基本参数空白或显示Call to undefined function make_hash() 最新的织梦版本(2018-01-09)修改了include文件夹中的common.func.php,增加了两个函数. 下载的模板文件夹中如果提供了common.func.php文件,很有可能没有这两个函数,于是会造成错误. 需要将这两个函数的代码粘贴到/include/common.func.php文件中,代码如下: function make_hash(){    $ran

还原dede数据后系统基本参数空白无显示的解决方法

有时dedecms开发的网站在更换空间还原数据后,出现“系统基本参数”空白,而且可以看到tag也没有了. 大家不妨看看后台“数据库备份/还原”处,已经还原后的表格中dede_sysconfig.dede_sys_set .(dede_taglist)记录数为0. 其实解决的方法很简单,我们从头说起: 首先在原来空间将数据备份,并上传到新空间,在data/backupdata/文件夹里. 首先更换空间后,重新安装,如果你的网站根目录里还有install文件夹(如果已经删掉了,那就重新下载个程序,把

modelSIM仿真时objects空白无显示问题

http://blog.csdn.net/yyywxk/article/details/68947172 笔者在做modelsIM实验时,在编译好相关文件后,准备进行相关仿真实验,此时意外发生了. 无论笔者怎么点击仿真界面,object页面下始终没有是空白没有任何东西.同时,下方的transcript页面底部一直显示loading.....在等待足够长的时间后,最终显示"failed to start simulation kernel". 对于这种状况,目前网络上的给出了两种方法.

可变卷积Deforable ConvNet 迁移训练自己的数据集 MXNet框架 GPU版

[引言] 最近在用可变卷积的rfcn 模型迁移训练自己的数据集, MSRA官方使用的MXNet框架 环境搭建及配置:http://www.cnblogs.com/andre-ma/p/8867031.html 一 参数修改: 1.1  ~/Deformable-ConvNets/experiments/rfcn/cfgs/resnet_v1_101_voc0712_rfcn_dcn_end2end_ohem.yaml  文件中修改两个参数 (yaml文件包含对应训练脚本的一切配置信息和超参数)

Android系统显示框架

1 Linux 驱动   FrameBuffer 在内核层,系统屏幕是使用一个称为帧缓冲区的硬件设备来描述的,而用户空间的应用程序可以通过设备文件/dev/fb0或者/dev/graphics /fb0来操作这个硬件设备.实际上,帧缓冲区本身并不是一个真正的硬件,它只不过是对显卡的一个抽象表示,不过,我们通过访帧缓冲区就可以间接地操作显 卡内存以及显卡中的其它寄存器 2 硬件抽象层(HAL)模块Gralloc 为了在屏幕中绘制一个指定的画面,我们需要: 1.  分配一个匹配屏幕大小的图形缓冲区

IT观察】网络通信、图片显示、数据库操作……Android程序员如何利用开源框架

每个Android 程序员都不是Android应用开发之路上孤军奋战的一个人,GitHub上浩如烟海的开源框架或类库就是前人为我们发明的轮子,有的轮子能提高软件性能,而有的轮子似乎是以牺牲性能为代价换取编程速度.擅长利用轮子的程序员已经遥遥领先,不擅长利用轮子的程序员总是嫌前人发明的轮子不够圆,自己造个方轮子上路后才发现落后了. 作者:玖哥来源:51CTO|2017-10-19 16:06 移动端 收藏 分享 [51CTO.com原创稿件]每个Android 程序员都不是Android应用开发之

iOS开发常用第三方开源框架 持续更新中...

键盘管理TPKeyboardAvoidingIQKeyboardManager 弹窗HUDMBProgressHUDSVProgressHUDUIView+Toast UIView显示提示CategoryToast-Swift Tosat-swift版本SnailPopupController 快速弹出自定义视图,支持自定义蒙版样式/过渡效果/手势拖动等 上下拉刷新MJRefreshSVPullToRefresh JSON解析MJExtension 网络请求AFNetworkingAlamofi