zoukankan      html  css  js  c++  java
  • DZNEmptyDataSet——空白数据集显示框架

    • GitHub地址:DZNEmptyDataSet
    • 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 导入

      支持 CocoaPods 导入
      pod 'DZNEmptyDataSet'
      导入
      #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];
          
          • 按钮点击高亮效果

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

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

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

            • 设置图片的 tintColor
  • 相关阅读:
    封装异常处理之坑
    30multipart/form-data和application/x-www-form-urlencoded的区别(二)urlencoded之自动deocde
    使用MAT时的Shallow Size和 Retained Size的区别
    当动态代理遇到ioc
    线程池的原理
    synchroned原理与对象头(yet)
    mysql压力测试与qps监控
    一种mysql jvm死锁
    Android Jni变量对照表
    结构体中使用函数指针
  • 原文地址:https://www.cnblogs.com/edensyd/p/9232975.html
Copyright © 2011-2022 走看看