Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f78f5c378 | |||
| c8fdd6998d | |||
| 134463e529 | |||
| ee59239c59 | |||
| f1e61aa9c0 | |||
| 135778aa1a |
@@ -191,7 +191,7 @@ func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection s
|
||||
|
||||
> 📣 **IMPORTANT!**
|
||||
>
|
||||
> If you return `SkeletonCollectionDataSource.automaticNumberOfRows` in the above method, it acts like the default behavior (i.e. it calculates how many cells needed to populate the whole tableview).
|
||||
> If you return `UITableView.automaticNumberOfSkeletonRows` in the above method, it acts like the default behavior (i.e. it calculates how many cells needed to populate the whole tableview).
|
||||
|
||||
There is only one method you need to implement to let Skeleton know the cell identifier. This method doesn't have default implementation:
|
||||
``` swift
|
||||
@@ -498,10 +498,10 @@ view.isHiddenWhenSkeletonIsActive = true // This works only when isSkeletonable
|
||||
**Don't modify user interaction when the skeleton is active**
|
||||
|
||||
|
||||
By default, user interaction is disabled for skeletonized items, but if you don't want to modify the user interaction indicator when skeleton is active, you can use the `isDisableWhenSkeletonIsActive` property:
|
||||
By default, the user interaction is disabled for skeletonized items, but if you don't want to modify the user interaction indicator when skeleton is active, you can use the `isUserInteractionDisabledWhenSkeletonIsActive` property:
|
||||
|
||||
```swift
|
||||
view.isDisableWhenSkeletonIsActive = false // The view will be active when the skeleton will be active.
|
||||
view.isUserInteractionDisabledWhenSkeletonIsActive = false // The view will be active when the skeleton will be active.
|
||||
```
|
||||
|
||||
**Debug**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "SkeletonView"
|
||||
s.version = "1.16.0"
|
||||
s.version = "1.17.1"
|
||||
s.summary = "An elegant way to show users that something is happening and also prepare them to which contents he is waiting"
|
||||
s.description = <<-DESC
|
||||
Today almost all apps have async processes, as API requests, long runing processes, etc. And while the processes are working, usually developers place a loading view to show users that something is going on.
|
||||
|
||||
@@ -31,14 +31,14 @@ extension CollectionSkeleton where Self: UIScrollView {
|
||||
func removeDummyDataSource(reloadAfter: Bool) {}
|
||||
|
||||
func disableUserInteraction() {
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = false
|
||||
isScrollEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
func enableUserInteraction() {
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = true
|
||||
isScrollEnabled = true
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public protocol SkeletonCollectionViewDataSource: UICollectionViewDataSource {
|
||||
|
||||
public extension SkeletonCollectionViewDataSource {
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return SkeletonCollectionDataSource.automaticNumberOfRows
|
||||
return UICollectionView.automaticNumberOfSkeletonItems
|
||||
}
|
||||
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView,
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
import UIKit
|
||||
|
||||
extension UICollectionView: CollectionSkeleton {
|
||||
public static let automaticNumberOfSkeletonItems = -1
|
||||
|
||||
var estimatedNumberOfRows: Int {
|
||||
guard let flowlayout = collectionViewLayout as? UICollectionViewFlowLayout else { return 0 }
|
||||
switch flowlayout.scrollDirection {
|
||||
|
||||
@@ -11,8 +11,6 @@ import UIKit
|
||||
public typealias ReusableCellIdentifier = String
|
||||
|
||||
class SkeletonCollectionDataSource: NSObject {
|
||||
static let automaticNumberOfRows = -1
|
||||
|
||||
weak var originalTableViewDataSource: SkeletonTableViewDataSource?
|
||||
weak var originalCollectionViewDataSource: SkeletonCollectionViewDataSource?
|
||||
var rowHeight: CGFloat = 0.0
|
||||
@@ -40,7 +38,7 @@ extension SkeletonCollectionDataSource: UITableViewDataSource {
|
||||
|
||||
let numberOfRows = originalTableViewDataSource.collectionSkeletonView(tableView, numberOfRowsInSection: section)
|
||||
|
||||
if numberOfRows == Self.automaticNumberOfRows {
|
||||
if numberOfRows == UITableView.automaticNumberOfSkeletonRows {
|
||||
return tableView.estimatedNumberOfRows
|
||||
} else {
|
||||
return numberOfRows
|
||||
@@ -68,7 +66,7 @@ extension SkeletonCollectionDataSource: UICollectionViewDataSource {
|
||||
|
||||
let numberOfItems = originalCollectionViewDataSource.collectionSkeletonView(collectionView, numberOfItemsInSection: section)
|
||||
|
||||
if numberOfItems == Self.automaticNumberOfRows {
|
||||
if numberOfItems == UICollectionView.automaticNumberOfSkeletonItems {
|
||||
return collectionView.estimatedNumberOfRows
|
||||
} else {
|
||||
return numberOfItems
|
||||
|
||||
@@ -16,7 +16,7 @@ public protocol SkeletonTableViewDataSource: UITableViewDataSource {
|
||||
|
||||
public extension SkeletonTableViewDataSource {
|
||||
func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return SkeletonCollectionDataSource.automaticNumberOfRows
|
||||
return UITableView.automaticNumberOfSkeletonRows
|
||||
}
|
||||
|
||||
func numSections(in collectionSkeletonView: UITableView) -> Int { return 1 }
|
||||
|
||||
@@ -11,6 +11,8 @@ import UIKit
|
||||
public typealias ReusableHeaderFooterIdentifier = String
|
||||
|
||||
extension UITableView: CollectionSkeleton {
|
||||
public static let automaticNumberOfSkeletonRows = -1
|
||||
|
||||
var estimatedNumberOfRows: Int {
|
||||
return Int(ceil(frame.height / rowHeight))
|
||||
}
|
||||
|
||||
@@ -12,9 +12,17 @@ extension UIView {
|
||||
nonContentSizeLayoutConstraints.filter { $0.firstAttribute == NSLayoutConstraint.Attribute.height }
|
||||
}
|
||||
|
||||
var skeletonHeightConstraints: [NSLayoutConstraint] {
|
||||
nonContentSizeLayoutConstraints.filter {
|
||||
$0.firstAttribute == NSLayoutConstraint.Attribute.height
|
||||
&& $0.identifier?.contains("SkeletonView.Constraint.Height") ?? false
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func setHeight(equalToConstant constant: CGFloat) -> NSLayoutConstraint {
|
||||
let heightConstraint = heightAnchor.constraint(equalToConstant: constant)
|
||||
heightConstraint.identifier = "SkeletonView.Constraint.Height.\(constant)"
|
||||
NSLayoutConstraint.activate([heightConstraint])
|
||||
return heightConstraint
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ enum ViewAssociatedKeys {
|
||||
static var buttonViewState = "buttonViewState"
|
||||
static var currentSkeletonConfig = "currentSkeletonConfig"
|
||||
static var skeletonCornerRadius = "skeletonCornerRadius"
|
||||
static var disableWhenSkeletonIsActive = "disableWhenSkeletonIsActive"
|
||||
static var disabledWhenSkeletonIsActive = "disabledWhenSkeletonIsActive"
|
||||
}
|
||||
// codebeat:enable[TOO_MANY_IVARS]
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ public extension UIView {
|
||||
}
|
||||
|
||||
@IBInspectable
|
||||
var isDisableWhenSkeletonIsActive: Bool {
|
||||
get { return disableWhenSkeletonIsActive }
|
||||
set { disableWhenSkeletonIsActive = newValue }
|
||||
var isUserInteractionDisabledWhenSkeletonIsActive: Bool {
|
||||
get { return disabledWhenSkeletonIsActive }
|
||||
set { disabledWhenSkeletonIsActive = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable
|
||||
@@ -41,9 +41,9 @@ public extension UIView {
|
||||
set { ao_set(newValue, pkey: &ViewAssociatedKeys.hiddenWhenSkeletonIsActive) }
|
||||
}
|
||||
|
||||
private var disableWhenSkeletonIsActive: Bool {
|
||||
get { return ao_get(pkey: &ViewAssociatedKeys.disableWhenSkeletonIsActive) as? Bool ?? true }
|
||||
set { ao_set(newValue, pkey: &ViewAssociatedKeys.disableWhenSkeletonIsActive) }
|
||||
private var disabledWhenSkeletonIsActive: Bool {
|
||||
get { return ao_get(pkey: &ViewAssociatedKeys.disabledWhenSkeletonIsActive) as? Bool ?? true }
|
||||
set { ao_set(newValue, pkey: &ViewAssociatedKeys.disabledWhenSkeletonIsActive) }
|
||||
}
|
||||
|
||||
private var skeletonableCornerRadius: Float {
|
||||
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
|
||||
extension UIView {
|
||||
@objc func prepareViewForSkeleton() {
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
@@ -47,10 +47,7 @@ extension UILabel {
|
||||
}
|
||||
}
|
||||
|
||||
func restoreBackupHeightConstraints() {
|
||||
heightConstraints.forEach {
|
||||
removeConstraint($0)
|
||||
}
|
||||
func restoreBackupHeightConstraintsIfNeeded() {
|
||||
guard !backupHeightConstraints.isEmpty else { return }
|
||||
NSLayoutConstraint.activate(backupHeightConstraints)
|
||||
backupHeightConstraints.removeAll()
|
||||
@@ -59,7 +56,7 @@ extension UILabel {
|
||||
override func prepareViewForSkeleton() {
|
||||
backgroundColor = .clear
|
||||
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
@@ -75,7 +72,7 @@ extension UITextView {
|
||||
override func prepareViewForSkeleton() {
|
||||
backgroundColor = .clear
|
||||
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
@@ -102,7 +99,7 @@ extension UIImageView {
|
||||
override func prepareViewForSkeleton() {
|
||||
backgroundColor = .clear
|
||||
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
@@ -116,7 +113,7 @@ extension UIButton {
|
||||
override func prepareViewForSkeleton() {
|
||||
backgroundColor = .clear
|
||||
|
||||
if isDisableWhenSkeletonIsActive {
|
||||
if isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ extension UIView: Recoverable {
|
||||
self.layer.cornerRadius = storedViewState.cornerRadius
|
||||
self.layer.masksToBounds = storedViewState.clipToBounds
|
||||
|
||||
if self.isDisableWhenSkeletonIsActive {
|
||||
if self.isUserInteractionDisabledWhenSkeletonIsActive {
|
||||
self.isUserInteractionEnabled = storedViewState.isUserInteractionsEnabled
|
||||
}
|
||||
|
||||
@@ -57,12 +57,16 @@ extension UILabel {
|
||||
override func recoverViewState(forced: Bool) {
|
||||
super.recoverViewState(forced: forced)
|
||||
startTransition { [weak self] in
|
||||
guard let storedLabelState = self?.labelState else { return }
|
||||
guard let self = self,
|
||||
let storedLabelState = self.labelState else {
|
||||
return
|
||||
}
|
||||
|
||||
self?.restoreBackupHeightConstraints()
|
||||
NSLayoutConstraint.deactivate(self.skeletonHeightConstraints)
|
||||
self.restoreBackupHeightConstraintsIfNeeded()
|
||||
|
||||
if self?.textColor == .clear || forced {
|
||||
self?.textColor = storedLabelState.textColor
|
||||
if self.textColor == .clear || forced {
|
||||
self.textColor = storedLabelState.textColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user