jsdw_ios/QuickLocation/UIKit/EmptyDataSet/EmptyDataSetView.swift

324 lines
13 KiB
Swift

//
// EmptyDataSetView.swift
// EmptyDataSet-Swift
//
// Created by YZF on 28/6/17.
// Copyright © 2017 Xiaoye. All rights reserved.
//
import Foundation
import UIKit
public class EmptyDataSetView: UIView {
lazy var stackView: UIStackView = {
let view = UIStackView(arrangedSubviews: [imageView, titleLabel, detailLabel, button])
view.axis = .vertical
view.spacing = 10
view.alignment = .center
view.distribution = .fill
view.setCustomSpacing(15, after: imageView)
view.setCustomSpacing(20, after: detailLabel)
return view
}()
internal lazy var contentView: UIView = {
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.backgroundColor = UIColor.clear
contentView.isUserInteractionEnabled = true
contentView.alpha = 0
return contentView
}()
internal lazy var imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = UIColor.clear
imageView.contentMode = .scaleAspectFit
imageView.isUserInteractionEnabled = false
imageView.accessibilityIdentifier = "empty set background image"
self.contentView.addSubview(imageView)
return imageView
}()
internal lazy var titleLabel: UILabel = {
let titleLabel = UILabel()
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.backgroundColor = UIColor.clear
titleLabel.font = UIFont.systemFont(ofSize: 27.0)
titleLabel.textColor = UIColor(white: 0.6, alpha: 1.0)
titleLabel.textAlignment = .center
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.numberOfLines = 0
titleLabel.accessibilityIdentifier = "empty set title"
self.contentView.addSubview(titleLabel)
return titleLabel
}()
internal lazy var detailLabel: UILabel = {
let detailLabel = UILabel()
detailLabel.translatesAutoresizingMaskIntoConstraints = false
detailLabel.backgroundColor = UIColor.clear
detailLabel.font = UIFont.systemFont(ofSize: 17.0)
detailLabel.textColor = UIColor(white: 0.6, alpha: 1.0)
detailLabel.textAlignment = .center
detailLabel.lineBreakMode = .byWordWrapping
detailLabel.numberOfLines = 0
detailLabel.accessibilityIdentifier = "empty set detail label"
self.contentView.addSubview(detailLabel)
return detailLabel
}()
internal lazy var button: UIButton = {
let button = UIButton()
button.titleLabel?.font = .systemFont(ofSize: 12)
button.layer.cornerRadius = 5.0
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = UIColor.clear
button.contentHorizontalAlignment = .center
button.contentVerticalAlignment = .center
button.accessibilityIdentifier = "empty set button"
button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 13, bottom: 10, right: 13)
self.contentView.addSubview(button)
return button
}()
private var canShowImage: Bool {
return imageView.image != nil
}
private var canShowTitle: Bool {
if let attributedText = titleLabel.attributedText {
return attributedText.length > 0
}
return false
}
private var canShowDetail: Bool {
if let attributedText = detailLabel.attributedText {
return attributedText.length > 0
}
return false
}
private var canShowButton: Bool {
if let attributedTitle = button.attributedTitle(for: .normal) {
return attributedTitle.length > 0
} else if let _ = button.image(for: .normal) {
return true
} else if let buttonText = button.title(for: .normal) {
return buttonText.length > 0
}
return false
}
internal var customView: UIView? {
willSet {
if let customView = customView {
customView.removeFromSuperview()
}
}
didSet {
if let customView = customView {
customView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(customView)
}
}
}
internal var fadeInOnDisplay = false
internal var verticalOffset: CGFloat = 0
internal var verticalSpace: CGFloat = 11
internal var didTapContentViewHandle: (() -> Void)?
internal var didTapDataButtonHandle: (() -> Void)?
internal var willAppearHandle: (() -> Void)?
internal var didAppearHandle: (() -> Void)?
internal var willDisappearHandle: (() -> Void)?
internal var didDisappearHandle: (() -> Void)?
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(contentView)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func didMoveToSuperview() {
if let superviewBounds = superview?.bounds {
frame = CGRect(x: 0, y: 0, width: superviewBounds.width, height: superviewBounds.height)
}
if fadeInOnDisplay {
UIView.animate(withDuration: 0.25) {
self.contentView.alpha = 1
}
} else {
contentView.alpha = 1
}
}
// MARK: - Action Methods
internal func removeAllConstraints() {
removeConstraints(constraints)
contentView.removeConstraints(contentView.constraints)
}
internal func prepareForReuse() {
titleLabel.text = nil
detailLabel.text = nil
imageView.image = nil
button.setImage(nil, for: .normal)
button.setImage(nil, for: .highlighted)
button.setAttributedTitle(nil, for: .normal)
button.setAttributedTitle(nil, for: .highlighted)
button.setBackgroundImage(nil, for: .normal)
button.setBackgroundImage(nil, for: .highlighted)
customView = nil
removeAllConstraints()
}
internal func setupViews() {
addSubview(stackView)
stackView.layoutChain
.centerX()
.centerY(self, offset: verticalOffset)
imageView.isHidden = !canShowImage
titleLabel.isHidden = !canShowTitle
detailLabel.isHidden = !canShowDetail
button.isHidden = !canShowButton
}
// MARK: - Auto-Layout Configuration
internal func setupConstraints() {
// First, configure the content view constaints
// The content view must alway be centered to its superview
let centerXConstraint = NSLayoutConstraint(item: contentView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0.0)
let centerYConstraint = NSLayoutConstraint(item: contentView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0.0)
self.addConstraints([centerXConstraint, centerYConstraint])
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[contentView]|", options: [], metrics: nil, views: ["contentView": contentView]))
// When a custom offset is available, we adjust the vertical constraints' constants
if (verticalOffset != 0 && constraints.count > 0) {
centerYConstraint.constant = verticalOffset
}
if let customView = customView {
let centerXConstraint = NSLayoutConstraint(item: customView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0.0)
let centerYConstraint = NSLayoutConstraint(item: customView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0.0)
let customViewHeight = customView.frame.height
let customViewWidth = customView.frame.width
var heightConstarint: NSLayoutConstraint!
var widthConstarint: NSLayoutConstraint!
if(customViewHeight == 0) {
heightConstarint = NSLayoutConstraint(item: customView, attribute: .height, relatedBy: .lessThanOrEqual, toItem: self, attribute: .height, multiplier: 1, constant: 0.0)
} else {
heightConstarint = NSLayoutConstraint(item: customView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: customViewHeight)
}
if(customViewWidth == 0) {
widthConstarint = NSLayoutConstraint(item: customView, attribute: .width, relatedBy: .lessThanOrEqual, toItem: self, attribute: .width, multiplier: 1, constant: 0.0)
} else {
widthConstarint = NSLayoutConstraint(item: customView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: customViewWidth)
}
// When a custom offset is available, we adjust the vertical constraints' constants
if (verticalOffset != 0) {
centerYConstraint.constant = verticalOffset
}
self.addConstraints([centerXConstraint, centerYConstraint])
self.addConstraints([heightConstarint, widthConstarint])
// contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[customView]|", options: [], metrics: nil, views: ["customView": customView]))
// contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[customView]|", options: [], metrics: nil, views: ["customView": customView]))
} else {
let width = frame.width > 0 ? frame.width : UIScreen.main.bounds.width
let padding = roundf(Float(width/16.0))
let verticalSpace = self.verticalSpace // Default is 11 pts
var subviewStrings: [String] = []
var views: [String: UIView] = [:]
let metrics = ["padding": padding]
// Assign the image view's horizontal constraints
if canShowImage {
imageView.isHidden = false
subviewStrings.append("imageView")
views[subviewStrings.last!] = imageView
contentView.addConstraint(NSLayoutConstraint.init(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: contentView, attribute: .centerX, multiplier: 1.0, constant: 0.0))
} else {
imageView.isHidden = true
}
// Assign the title label's horizontal constraints
if (canShowTitle) {
titleLabel.isHidden = false
subviewStrings.append("titleLabel")
views[subviewStrings.last!] = titleLabel
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(padding)-[titleLabel(>=0)]-(padding)-|", options: [], metrics: metrics, views: views))
} else {
titleLabel.isHidden = true
}
// Assign the detail label's horizontal constraints
if (canShowDetail) {
detailLabel.isHidden = false
subviewStrings.append("detailLabel")
views[subviewStrings.last!] = detailLabel
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(padding)-[detailLabel(>=0)]-(padding)-|", options: [], metrics: metrics, views: views))
} else {
detailLabel.isHidden = true
}
// Assign the button's horizontal constraints
if (canShowButton) {
button.isHidden = false
subviewStrings.append("button")
views[subviewStrings.last!] = button
contentView.addConstraint(NSLayoutConstraint.init(item: button, attribute: .centerX, relatedBy: .equal, toItem: contentView, attribute: .centerX, multiplier: 1.0, constant: 0.0))
// contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[button]", options: [], metrics: metrics, views: views))
} else {
button.isHidden = true
}
var verticalFormat = String()
// Build a dynamic string format for the vertical constraints, adding a margin between each element. Default is 11 pts.
for i in 0 ..< subviewStrings.count {
let string = subviewStrings[i]
verticalFormat += "[\(string)]"
if i < subviewStrings.count - 1 {
verticalFormat += "-(\(verticalSpace))-"
}
}
// Assign the vertical constraints to the content view
if !verticalFormat.isEmpty {
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|\(verticalFormat)|", options: [], metrics: metrics, views: views))
}
}
}
}