EmptyPage(空白页组件)原理与使用

栏目: IOS · 发布时间: 5年前

内容简介:app 显示列表内容时, 在某一时刻可能数据为空(等待网络请求/网络请求失败)等, 添加一个空白指示页将有效缓解用户可能造成的焦虑或混乱. 并可以帮助用户处理问题.市面上已经有部分成熟的空白页框架,最典型的就是使用但是其使用

app 显示列表内容时, 在某一时刻可能数据为空(等待网络请求/网络请求失败)等, 添加一个空白指示页将有效缓解用户可能造成的焦虑或混乱. 并可以帮助用户处理问题.

市面上已经有部分成熟的空白页框架,最典型的就是使用 DZNEmptyDataSet .

但是其使用 DZNEmptyDataSetDelegate , DZNEmptyDataSetSource 来定制空白页元素,使用时较为繁琐.

笔者借鉴其原理的基础上,制作了对标框架(单向对标) EmptyPage 来简化日常项目开发.

前言

EmptyPage 历时1年, 在我司项目中稳定使用迭代6个版本,算是比较稳定.

支持UICollectionView & UITableView.

ps: 目前阶段只提供 swift 版本.

EmptyPage(空白页组件)原理与使用
EmptyPage(空白页组件)原理与使用

实现原理

该核心部分 作为一个单独的子库 实现, 可使用 以下方式单独引用.

pod 'EmptyPage/Core'
复制代码

具体代码可查阅 Github Link , 超级简单.

  1. UIScrollView 添加 emptyView 对象作为空白页实例:

    public extension UIScrollView {
      public var emptyView: UIView?
    }
    复制代码
  2. Method Swizzling 方式替换掉 UITableView \ UICollectionView 中部分相关函数.以下拿 UITableView 举例:

    // DZNEmptyDataSet 对 autolayout 项目不太友好. (也可能本人没深度使用...)
    // EmptyPage 
    // UITableView frame 变化相关函数
    open func layoutSubviews()
    open func layoutIfNeeded()
    // 数据源增减相关函数
    open func insertRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation)
    open func deleteRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation)
    open func insertSections(_ sections: IndexSet, with animation: UITableView.RowAnimation)
    open func deleteSections(_ sections: IndexSet, with animation: UITableView.RowAnimation)
    open func reloadData()
    复制代码
  3. 在数据/frame变化时判断空白页显示与隐藏.

    func setEmptyView(event: () -> ()) {
        oldEmptyView?.removeFromSuperview()
        event()
        guard bounds.width != 0, bounds.height != 0 else { return }
        var isHasRows = false
        let sectionCount = dataSource?.numberOfSections?(in: self) ?? numberOfSections
        for index in 0..<sectionCount {
          if numberOfRows(inSection: index) > 0 {
            isHasRows = true
            break
          }
        }
        isScrollEnabled = isHasRows
        if isHasRows {
          emptyView?.removeFromSuperview()
          return
        }
        guard let view = emptyView else{ return }
        view.frame = bounds
        addSubview(view)
        sendSubview(toBack: view)
      }
    复制代码
  4. 使用

    UITableView().emptyView = CustomView()
    UICollectionView().emptyView = CustomView()
    复制代码

    UITableView().emptyView 第一次被赋值时才会进行 Method Swizzling 相关函数.

模板视图

DZNEmptyDataSet 的成功离不开其可高度定制化的模板视图.但其繁琐的 delegate apis 远不如自定义视图来的方便, 其对自定义视图的支持也并不友善.

EmptyPage 优先支持 自定义视图,并附赠 3 套可以凑合看的模板视图(支持超级高自定义调节,但毕竟UI我们说了不算...)

采用 以下方式 则包含该部分内容:

pod 'EmptyPage'
复制代码
  1. 自定义视图

    • 仅支持autolayout布局模式

      不使用 autolayout 模式:

      pod 'EmptyPage/Core'
      UITableView().emptyView = CustomView()
      
    • 自定义视图需要autolayout实现自适应高

      可以参考 内置的几套模板视图的约束实现.

    • 添加 EmptyPageContentViewProtocol 协议

      该协议默认实现了将自定义视图居中约束至一个 backgroundView 上.

      通用性考虑: backgroundView.frame 与 tableView.frame 相同

      示例:

      class CustomView: EmptyPageContentViewProtocol{
          ...
      }
      
      let customView = CustomView()
      UITableView().emptyView = customView.mix()
      复制代码

      不添加该协议,可采用以下方式:

      UITableView().emptyView = EmptyPageView.mix(view: customView)

    • 视图关系

      EmptyPage(空白页组件)原理与使用
  2. 内置模板视图

    **特性: **

    1. 支持链式调用.
    2. 元素支持高度自定义.
    3. 同样依照自定义视图的标准实现.

    ps: 完全等同于提前写好的自定义模板视图.

    • 目前可以选择3套基本的模板视图.
      • 文字模板( EmptyPageView.ContentView.onlyText )

      • 图片模板( EmptyPageView.ContentView.onlyImage )

      • 混合模板( EmptyPageView.ContentView.standard )

    EmptyPage(空白页组件)原理与使用
    EmptyPage(空白页组件)原理与使用
    EmptyPage(空白页组件)原理与使用
    • 使用

      • 示例:

        UITableView().emptyView = EmptyPageView.ContentView.standard
        	.change(hspace: .button, value: 80)
        	.change(height: .button, value: 60)
        	.change(hspace: .image, value: 15)
        	.config(button: { (item) in
        		item.backgroundColor = UIColor.blue
        		item.contentEdgeInsets = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 20)
        	})
        	.set(image: UIImage(named: "empty-1002")!)
        	.set(title: "Connection failure", color: UIColor.black, font: UIFont.boldSystemFont(ofSize: 24))
        	.set(text: "Something has gone wrong with the internet connection. Let's give it another shot.", color: UIColor.black, font: UIFont.systemFont(ofSize: 15))
        	.set(buttonTitle: "TRY AGAIN")
        	.set(tap: {
        	// 点击事件
        	})
        	.mix()
        复制代码
    • Apis

      模板视图中总结起来只有三种配置函数:

      • 约束配置函数: func change(...) -> Self

        约束函数具体可配置项采用枚举的形式限定.(以免改变/冲突自适应高度相关约束)

        enum HSpaceType { } // 修改视图水平方向上的间距

        enum VSpaceType { } // 修改视图垂直方向上的间距

        enum HeightType { } // 修改视图具体高度

        例如:

        standardView.change(hspace: .button, value: 80)
        			.change(height: .button, value: 60)
        复制代码
      • 控件配置函数: func set(...) -> Self

        提供了简单的文本/字体/图片/颜色配置.例如:

        standardView.set(title: "Connection failure", color: UIColor.black, font: UIFont.boldSystemFont(ofSize: 24))
        复制代码
      • 控件自定义配置函数: func config(element: { (element) in ... }) -> Self

        返回一个完整的控件,可供深度配置. 例如:

        standardView.config(button: { (item) in
        	item.backgroundColor = UIColor.blue
        	item.contentEdgeInsets = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 20)
        	})
        复制代码
      • 视图混合函数 func mix() :

        该函数由 EmptyPageContentViewProtocol 协议默认实现.

        作用: 将视图约束至 backgroundView 上

        ps: 别忘了...


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Go语言实战

Go语言实战

威廉·肯尼迪 (William Kennedy)、布赖恩·克特森 (Brian Ketelsen)、埃里克·圣马丁 (Erik St.Martin) / 李兆海 / 人民邮电出版社 / 2017-3-1 / CNY 59.00

Go语言结合了底层系统语言的能力以及现代语言的高级特性,旨在降低构建简单、可靠、高效软件的门槛。本书向读者提供一个专注、全面且符合语言习惯的视角。Go语言实战同时关注语言的规范和实现,涉及的内容包括语法、类型系统、并发、管道、测试,以及其他一些主题。一起来看看 《Go语言实战》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具