// // EmptyDataSet.swift // JiuLaiBao // // Created by 霹雳火 on 01/06/2018. // Copyright © 2018 GuoXiaoMei. All rights reserved. // import Foundation import RxSwift import UIKit private var emptyDataSetAssociatedKey: UInt8 = 0 public extension DLWrapper where Base: UIScrollView { /// DLEmptyDataSet var emptyDataSet: DLEmptyDataSet? { objc_getAssociatedObject(base, &emptyDataSetAssociatedKey) as? DLEmptyDataSet } /// /// - Parameters: /// - customEmptyHandler: 自定义Empty样式回调,可以对empty进行设置 /// - customButtonDidTap: 自定义按钮点击回调 /// - didTapRefresh: 网络失败按钮点击事件回调 /// - Returns: DLEmptyDataSet @discardableResult func addEmptyDataSet(customEmptyHandler: ((DLEmptyDataSet) -> Void)? = nil, customButtonDidTap: (() -> Void)? = nil, didTapRefresh: (() -> Void)? = nil) -> DLEmptyDataSet { let emptyDataSet = DLEmptyDataSet(scrollView: base) emptyDataSet.didTapRefresh = didTapRefresh emptyDataSet.customDidTap = customButtonDidTap customEmptyHandler?(emptyDataSet) objc_setAssociatedObject(base, &emptyDataSetAssociatedKey, emptyDataSet, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return emptyDataSet } } public struct EmptyDataSetConfig { static public var titleColor = UIColor(hexStr: "#666666") static public var detailColor = UIColor(hexStr: "#999999") static public var emptyNoDataTitle = "oapp_EmptyNoData" static public var emptyNoDataDetail = "" static public var emptyNoDataImage = UIImage(named: "empty_data") static public var emptyNetworkErrorTitle = "请检查网络连接" static public var emptyNetworkErrorDetail = "" static public var emptyNetworkErrorImage = UIImage(named: "empty_network") static public var emptyReloadButtonImage = UIImage(named: "empty_reload") static public var reloadButtonTitle = "重新加载" static public var customButtonTitle = "" static public var backgroundColor: UIColor = .clear static public var spaceHeight: CGFloat = 15.0 /// 重置 public static func resetConfig() { titleColor = UIColor(hexStr: "#666666") detailColor = UIColor(hexStr: "#999999") emptyNoDataTitle = "暂无数据" emptyNoDataDetail = "" emptyNoDataImage = UIImage(named: "empty_data") emptyNetworkErrorTitle = "请检查网络连接" emptyNetworkErrorDetail = "" emptyNetworkErrorImage = UIImage(named: "empty_network") emptyReloadButtonImage = UIImage(named: "empty_reload") customButtonTitle = "" backgroundColor = .clear } } public class DLEmptyDataSet: NSObject { private var disposeBag = DisposeBag() private weak var scrollView: UIScrollView! private var refreshStatus: RefreshStatus? private var isEmptyVariable = BehaviorSubject(value: nil) // 是否开始就显示empty占位图 private var shouldBeForcedToDisplay = false public var titleColor = EmptyDataSetConfig.titleColor public var detailColor = EmptyDataSetConfig.detailColor public var emptyNoDataTitle = EmptyDataSetConfig.emptyNoDataTitle public var emptyNoDataDetail = EmptyDataSetConfig.emptyNoDataDetail public var emptyNoDataImage = EmptyDataSetConfig.emptyNoDataImage public var emptyNetworkErrorTitle = EmptyDataSetConfig.emptyNetworkErrorTitle public var emptyNetworkErrorDetail = EmptyDataSetConfig.emptyNetworkErrorDetail public var emptyNetworkErrorImage = EmptyDataSetConfig.emptyNetworkErrorImage public var emptyReloadButtonImage = EmptyDataSetConfig.emptyReloadButtonImage public var reloadButtonTitle = EmptyDataSetConfig.reloadButtonTitle public var customButtonTitle = EmptyDataSetConfig.customButtonTitle public var backgroundColor: UIColor = EmptyDataSetConfig.backgroundColor public var spaceHeight: CGFloat = EmptyDataSetConfig.spaceHeight public var offsetY: CGFloat = 0 { didSet { scrollView.reloadEmptyDataSet() } } public var didTapRefresh: (() -> Void)? public var customDidTap: (() -> Void)? required public init(scrollView: UIScrollView) { super.init() self.scrollView = scrollView scrollView.emptyDataSetSource = self scrollView.emptyDataSetDelegate = self isEmptyVariable.asObservable().subscribe(onNext: { [unowned self] value in if let _ = value { self.scrollView.reloadEmptyDataSet() } }).disposed(by: disposeBag) } public func update(status: RefreshStatus?, isEmpty: Bool, shouldForcedDisplay: Bool = false) { refreshStatus = status shouldBeForcedToDisplay = shouldForcedDisplay isEmptyVariable.onNext(isEmpty) } public func reset() { shouldBeForcedToDisplay = false refreshStatus = nil isEmptyVariable.onNext(false) } } extension DLEmptyDataSet: EmptyDataSetSource, EmptyDataSetDelegate { // MARK: DZNEmptyDataSetSource public func title(forEmptyDataSet _: UIScrollView) -> NSAttributedString? { let text = refreshStatus == .invalidData ? emptyNetworkErrorTitle : emptyNoDataTitle let attributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 13), .foregroundColor: titleColor] return NSAttributedString(string: text, attributes: attributes) } public func description(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? { let text = refreshStatus == .invalidData ? emptyNetworkErrorDetail : emptyNoDataDetail let attributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 13), .foregroundColor: detailColor] return NSAttributedString(string: text, attributes: attributes) } public func buttonTitle(forEmptyDataSet scrollView: UIScrollView, for state: UIControl.State) -> String? { return refreshStatus == .invalidData ? " \(reloadButtonTitle) " : customButtonTitle.isEmpty ? nil : " \(customButtonTitle) " } public func buttonAttributedTitle(forEmptyDataSet scrollView: UIScrollView, for state: UIControl.State) -> NSAttributedString? { // let errorAttri = NSAttributedString(string: "oapp_Reload".localizedString, // font: UIFont.systemFont(ofSize: 15), // color: UIColor.dl.rgb666666) // return refreshStatus == .invalidData ? errorAttri : nil return nil } public func image(forEmptyDataSet _: UIScrollView) -> UIImage? { return refreshStatus == .invalidData ? emptyNetworkErrorImage : emptyNoDataImage } // public func buttonImage(forEmptyDataSet scrollView: UIScrollView!, for state: UIControl.State) -> UIImage! { // return refreshStatus == .invalidData ? emptyReloadButtonImage : nil // } public func backgroundColor(forEmptyDataSet _: UIScrollView) -> UIColor? { return backgroundColor } // MARK: DZNEmptyDataSetDelegate public func emptyDataSetShouldDisplay(_: UIScrollView) -> Bool { // 判断是否正在刷新 guard refreshStatus != nil, let isDisplay = try? isEmptyVariable.value() else { return false } // 网络请求错误或者请求数据为空 return isDisplay } public func emptyDataSetShouldAllowTouch(_ scrollView: UIScrollView) -> Bool { return true } public func emptyDataSetShouldAllowScroll(_ scrollView: UIScrollView) -> Bool { return true } public func emptyDataSet(_ scrollView: UIScrollView, didTapView view: UIView) { } public func emptyDataSet(_ scrollView: UIScrollView, didTapButton button: UIButton) { if customButtonTitle.isEmpty { reset() didTapRefresh?() } else { customDidTap?() } } public func emptyDataSetWillAppear(_ scrollView: UIScrollView) { scrollView.contentOffset = CGPoint() } public func verticalOffset(forEmptyDataSet scrollView: UIScrollView) -> CGFloat { return offsetY } public func spaceHeight(forEmptyDataSet scrollView: UIScrollView) -> CGFloat { return spaceHeight } @objc public func emptyDataSetShouldBeForcedToDisplay(_ scrollView: UIScrollView) -> Bool { return shouldBeForcedToDisplay } }