Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9613f36f19 | |||
| 38b42f8713 | |||
| 4c3c996816 | |||
| 3284db700c | |||
| 7958826036 | |||
| fb1a5e3b8e | |||
| fcae5ac799 | |||
| 9063a5bc9f | |||
| 605b1e368f | |||
| 6e769ed0d4 | |||
| e880c00815 | |||
| 75ec8bc1f1 | |||
| e3e8d5b51a | |||
| ad511ee64c | |||
| 86bb15bc25 | |||
| c49e4505c8 | |||
| 13b041b5f1 |
@@ -1,6 +1,26 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file
|
||||
|
||||
## [Needed(1.1)(WIP)](https://github.com/Juanpe/SkeletonView/releases/tag/1.1)
|
||||
|
||||
### New
|
||||
- Now ```SkeletonView```supports **UICollectionViews**! 🎉. (thanks @Renatdz)
|
||||
|
||||
### Bug fixes
|
||||
- Solved issue #39. Gradient animation did not work when app becomes active.
|
||||
|
||||
|
||||
## [Resizable (1.0.5)](https://github.com/Juanpe/SkeletonView/releases/tag/1.0.5)
|
||||
|
||||
### New
|
||||
- Now you can use table views with resizable cells.
|
||||
|
||||
### Bug fixes
|
||||
- Solved issues.
|
||||
[#17](https://github.com/Juanpe/SkeletonView/issues/17),
|
||||
[#30](https://github.com/Juanpe/SkeletonView/issues/30),
|
||||
[#34](https://github.com/Juanpe/SkeletonView/issues/34).
|
||||
|
||||
## [Filled or not (1.0.4)](https://github.com/Juanpe/SkeletonView/releases/tag/1.0.4)
|
||||
|
||||
### New
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Constants.swift
|
||||
// SkeletonView-iOS
|
||||
//
|
||||
// Created by Renato Mendes on 28/11/2017.
|
||||
// Copyright © 2017 SkeletonView. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
let colors = [(UIColor.turquoise,"turquoise"), (UIColor.emerald,"emerald"), (UIColor.peterRiver,"peterRiver"), (UIColor.amethyst,"amethyst"),(UIColor.wetAsphalt,"wetAsphalt"), (UIColor.nephritis,"nephritis"), (UIColor.belizeHole,"belizeHole"), (UIColor.wisteria,"wisteria"), (UIColor.midnightBlue,"midnightBlue"), (UIColor.sunFlower,"sunFlower"), (UIColor.carrot,"carrot"), (UIColor.alizarin,"alizarin"),(UIColor.clouds,"clouds"), (UIColor.concrete,"concrete"), (UIColor.flatOrange,"flatOrange"), (UIColor.pumpkin,"pumpkin"), (UIColor.pomegranate,"pomegranate"), (UIColor.silver,"silver"), (UIColor.asbestos,"asbestos")]
|
||||
@@ -9,8 +9,6 @@
|
||||
import UIKit
|
||||
import SkeletonView
|
||||
|
||||
let colors = [(UIColor.turquoise,"turquoise"), (UIColor.emerald,"emerald"), (UIColor.peterRiver,"peterRiver"), (UIColor.amethyst,"amethyst"),(UIColor.wetAsphalt,"wetAsphalt"), (UIColor.nephritis,"nephritis"), (UIColor.belizeHole,"belizeHole"), (UIColor.wisteria,"wisteria"), (UIColor.midnightBlue,"midnightBlue"), (UIColor.sunFlower,"sunFlower"), (UIColor.carrot,"carrot"), (UIColor.alizarin,"alizarin"),(UIColor.clouds,"clouds"), (UIColor.concrete,"concrete"), (UIColor.flatOrange,"flatOrange"), (UIColor.pumpkin,"pumpkin"), (UIColor.pomegranate,"pomegranate"), (UIColor.silver,"silver"), (UIColor.asbestos,"asbestos")]
|
||||
|
||||
class ViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var tableview: UITableView! {
|
||||
|
||||
@@ -60,7 +60,7 @@ Enjoy it! 🙂
|
||||
### 📋 Supported OS & SDK Versions
|
||||
|
||||
* iOS 9.0+
|
||||
* Swift 4 (Swift 3 compatible)
|
||||
* Swift 4
|
||||
|
||||
### 🔮 Example
|
||||
|
||||
@@ -152,7 +152,9 @@ avatarImageView.isSkeletonable = true
|
||||
|
||||
### 🌿 Collections
|
||||
|
||||
Currently, ```SkeletonView``` only is compatible with ```UITableView```. We are working hard to support ```UICollectionView``` too 💪🏼
|
||||
Now, ```SkeletonView``` is compatible with ```UITableView``` and ```UICollectionView```.
|
||||
|
||||
###### UITableView
|
||||
|
||||
If you want to show the skeleton in a ```UITableView```, you need to conform to ```SkeletonTableViewDataSource``` protocol.
|
||||
|
||||
@@ -193,6 +195,20 @@ There is only one method you need to implement to let Skeleton know the cell ide
|
||||
> **IMPORTANT!**
|
||||
> If you are using resizable cells (`tableView.rowHeight = UITableViewAutomaticDimension` ), it's mandatory define the `estimatedRowHeight`.
|
||||
|
||||
###### UICollectionView
|
||||
|
||||
For ```UICollectionView```, you need to conform to ```SkeletonCollectionViewDataSource``` protocol.
|
||||
|
||||
``` swift
|
||||
public protocol SkeletonCollectionViewDataSource: UICollectionViewDataSource {
|
||||
func numSections(in collectionSkeletonView: UICollectionView) -> Int
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier
|
||||
}
|
||||
```
|
||||
|
||||
The rest of the process is the same as ```UITableView```
|
||||
|
||||
### 📰 Multiline text
|
||||
|
||||
|
||||
@@ -312,7 +328,7 @@ Coming soon...😅
|
||||
* [x] Set the filling percent of the last line in multiline elements
|
||||
* [x] Add more gradient animations
|
||||
* [x] Supported resizable cells
|
||||
* [ ] CollectionView compatible
|
||||
* [x] CollectionView compatible
|
||||
* [ ] Add recovery state
|
||||
* [ ] Custom collections compatible
|
||||
* [ ] Add animations when it shows/hides the skeletons
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "SkeletonView"
|
||||
s.version = "1.0.5"
|
||||
s.version = "1.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.
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
88DEA97F1FCDBD78006C80EF /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88DEA97D1FCDBD1F006C80EF /* Constants.swift */; };
|
||||
8933C7851EB5B820000D00A4 /* SkeletonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7841EB5B820000D00A4 /* SkeletonView.swift */; };
|
||||
F51DE1091FBF70A70037919A /* SkeletonAnimationBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F51DE1081FBF70A70037919A /* SkeletonAnimationBuilder.swift */; };
|
||||
F5307E2C1FAF6BC900EE67C5 /* SkeletonGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E2B1FAF6BC900EE67C5 /* SkeletonGradient.swift */; };
|
||||
F5307E2E1FB0E5E400EE67C5 /* UIView+Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E2D1FB0E5E400EE67C5 /* UIView+Frame.swift */; };
|
||||
F5307E301FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E2F1FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift */; };
|
||||
F5307E321FB0F42F00EE67C5 /* RecursiveProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E311FB0F42F00EE67C5 /* RecursiveProtocol.swift */; };
|
||||
F5307E371FB1076E00EE67C5 /* SkeletonUITableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E361FB1076E00EE67C5 /* SkeletonUITableViewDataSource.swift */; };
|
||||
F5307E391FB1078E00EE67C5 /* SkeletonUICollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E381FB1078E00EE67C5 /* SkeletonUICollectionViewDataSource.swift */; };
|
||||
F5307E371FB1076E00EE67C5 /* SkeletonTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E361FB1076E00EE67C5 /* SkeletonTableViewDataSource.swift */; };
|
||||
F5307E391FB1078E00EE67C5 /* SkeletonCollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E381FB1078E00EE67C5 /* SkeletonCollectionViewDataSource.swift */; };
|
||||
F5307E3B1FB123C100EE67C5 /* ContainsMultilineText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E3A1FB123C100EE67C5 /* ContainsMultilineText.swift */; };
|
||||
F5307E411FB3B84500EE67C5 /* SkeletonView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* SkeletonView.framework */; };
|
||||
F5307E421FB3B84500EE67C5 /* SkeletonView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* SkeletonView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@@ -22,6 +23,8 @@
|
||||
F54CF5E52024CEB000330B0D /* UITableView+CollectionSkeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54CF5E22024CEAF00330B0D /* UITableView+CollectionSkeleton.swift */; };
|
||||
F54CF5E62024CEB000330B0D /* UICollectionView+CollectionSkeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54CF5E32024CEB000330B0D /* UICollectionView+CollectionSkeleton.swift */; };
|
||||
F56B94461FAE20AF0095662F /* PrepareForSkeletonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F56B94451FAE20AF0095662F /* PrepareForSkeletonProtocol.swift */; };
|
||||
F587FB84202CBFC8002DB5FE /* SkeletonFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F587FB83202CBFC8002DB5FE /* SkeletonFlow.swift */; };
|
||||
F587FB86202CEC95002DB5FE /* UIView+UIApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F587FB85202CEC95002DB5FE /* UIView+UIApplicationDelegate.swift */; };
|
||||
F5F622411FAC6E31007C062A /* UIColor+Skeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F622401FAC6E31007C062A /* UIColor+Skeleton.swift */; };
|
||||
F5F622431FAC81FD007C062A /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F622421FAC81FD007C062A /* CALayer+Extensions.swift */; };
|
||||
F5F622451FACA338007C062A /* Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5F622441FACA338007C062A /* Cell.swift */; };
|
||||
@@ -63,6 +66,7 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
52D6D97C1BEFF229002C0205 /* SkeletonView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SkeletonView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
88DEA97D1FCDBD1F006C80EF /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
8933C7841EB5B820000D00A4 /* SkeletonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SkeletonView.swift; sourceTree = "<group>"; };
|
||||
AD2FAA261CD0B6D800659CF4 /* SkeletonView.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SkeletonView.plist; sourceTree = "<group>"; };
|
||||
F51DE1081FBF70A70037919A /* SkeletonAnimationBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonAnimationBuilder.swift; sourceTree = "<group>"; };
|
||||
@@ -70,13 +74,15 @@
|
||||
F5307E2D1FB0E5E400EE67C5 /* UIView+Frame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Frame.swift"; sourceTree = "<group>"; };
|
||||
F5307E2F1FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonDefaultConfig.swift; sourceTree = "<group>"; };
|
||||
F5307E311FB0F42F00EE67C5 /* RecursiveProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecursiveProtocol.swift; sourceTree = "<group>"; };
|
||||
F5307E361FB1076E00EE67C5 /* SkeletonUITableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonUITableViewDataSource.swift; sourceTree = "<group>"; };
|
||||
F5307E381FB1078E00EE67C5 /* SkeletonUICollectionViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonUICollectionViewDataSource.swift; sourceTree = "<group>"; };
|
||||
F5307E361FB1076E00EE67C5 /* SkeletonTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonTableViewDataSource.swift; sourceTree = "<group>"; };
|
||||
F5307E381FB1078E00EE67C5 /* SkeletonCollectionViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonCollectionViewDataSource.swift; sourceTree = "<group>"; };
|
||||
F5307E3A1FB123C100EE67C5 /* ContainsMultilineText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainsMultilineText.swift; sourceTree = "<group>"; };
|
||||
F54CF5E12024CEAF00330B0D /* UIView+CollectionSkeleton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+CollectionSkeleton.swift"; sourceTree = "<group>"; };
|
||||
F54CF5E22024CEAF00330B0D /* UITableView+CollectionSkeleton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+CollectionSkeleton.swift"; sourceTree = "<group>"; };
|
||||
F54CF5E32024CEB000330B0D /* UICollectionView+CollectionSkeleton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UICollectionView+CollectionSkeleton.swift"; sourceTree = "<group>"; };
|
||||
F56B94451FAE20AF0095662F /* PrepareForSkeletonProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepareForSkeletonProtocol.swift; sourceTree = "<group>"; };
|
||||
F587FB83202CBFC8002DB5FE /* SkeletonFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonFlow.swift; sourceTree = "<group>"; };
|
||||
F587FB85202CEC95002DB5FE /* UIView+UIApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+UIApplicationDelegate.swift"; sourceTree = "<group>"; };
|
||||
F5F622401FAC6E31007C062A /* UIColor+Skeleton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Skeleton.swift"; sourceTree = "<group>"; };
|
||||
F5F622421FAC81FD007C062A /* CALayer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Extensions.swift"; sourceTree = "<group>"; };
|
||||
F5F622441FACA338007C062A /* Cell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cell.swift; sourceTree = "<group>"; };
|
||||
@@ -153,6 +159,7 @@
|
||||
F5307E2B1FAF6BC900EE67C5 /* SkeletonGradient.swift */,
|
||||
F5F899E81FAB9D2B002E8FDA /* SkeletonLayer.swift */,
|
||||
8933C7841EB5B820000D00A4 /* SkeletonView.swift */,
|
||||
F587FB83202CBFC8002DB5FE /* SkeletonFlow.swift */,
|
||||
);
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
@@ -170,8 +177,8 @@
|
||||
children = (
|
||||
F5F899EC1FAB9F04002E8FDA /* CollectionSkeletonProtocol.swift */,
|
||||
F5F899EA1FAB9DA3002E8FDA /* SkeletonCollectionDataSource.swift */,
|
||||
F5307E381FB1078E00EE67C5 /* SkeletonUICollectionViewDataSource.swift */,
|
||||
F5307E361FB1076E00EE67C5 /* SkeletonUITableViewDataSource.swift */,
|
||||
F5307E381FB1078E00EE67C5 /* SkeletonCollectionViewDataSource.swift */,
|
||||
F5307E361FB1076E00EE67C5 /* SkeletonTableViewDataSource.swift */,
|
||||
F54CF5E32024CEB000330B0D /* UICollectionView+CollectionSkeleton.swift */,
|
||||
F54CF5E22024CEAF00330B0D /* UITableView+CollectionSkeleton.swift */,
|
||||
F54CF5E12024CEAF00330B0D /* UIView+CollectionSkeleton.swift */,
|
||||
@@ -186,6 +193,7 @@
|
||||
F5F622401FAC6E31007C062A /* UIColor+Skeleton.swift */,
|
||||
F5307E2D1FB0E5E400EE67C5 /* UIView+Frame.swift */,
|
||||
F5F899CF1FAA6A4D002E8FDA /* UIView+IBInspectable.swift */,
|
||||
F587FB85202CEC95002DB5FE /* UIView+UIApplicationDelegate.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@@ -205,6 +213,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F5F899F41FABA607002E8FDA /* AppDelegate.swift */,
|
||||
88DEA97D1FCDBD1F006C80EF /* Constants.swift */,
|
||||
F5F899F61FABA607002E8FDA /* ViewController.swift */,
|
||||
F5F622441FACA338007C062A /* Cell.swift */,
|
||||
F5F899F81FABA607002E8FDA /* Main.storyboard */,
|
||||
@@ -286,17 +295,17 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0910;
|
||||
LastUpgradeCheck = 0900;
|
||||
LastUpgradeCheck = 0920;
|
||||
ORGANIZATIONNAME = SkeletonView;
|
||||
TargetAttributes = {
|
||||
52D6D97B1BEFF229002C0205 = {
|
||||
CreatedOnToolsVersion = 7.1;
|
||||
DevelopmentTeam = PTS5FAP7XL;
|
||||
DevelopmentTeam = KWEMDK92F4;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
F5F899F11FABA607002E8FDA = {
|
||||
CreatedOnToolsVersion = 9.1;
|
||||
DevelopmentTeam = PTS5FAP7XL;
|
||||
DevelopmentTeam = KWEMDK92F4;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
@@ -347,7 +356,7 @@
|
||||
files = (
|
||||
F5F899D01FAA6A4D002E8FDA /* UIView+IBInspectable.swift in Sources */,
|
||||
F54CF5E42024CEB000330B0D /* UIView+CollectionSkeleton.swift in Sources */,
|
||||
F5307E371FB1076E00EE67C5 /* SkeletonUITableViewDataSource.swift in Sources */,
|
||||
F5307E371FB1076E00EE67C5 /* SkeletonTableViewDataSource.swift in Sources */,
|
||||
8933C7851EB5B820000D00A4 /* SkeletonView.swift in Sources */,
|
||||
F5307E301FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift in Sources */,
|
||||
F54CF5E52024CEB000330B0D /* UITableView+CollectionSkeleton.swift in Sources */,
|
||||
@@ -355,12 +364,14 @@
|
||||
F5F622431FAC81FD007C062A /* CALayer+Extensions.swift in Sources */,
|
||||
F5F899ED1FAB9F04002E8FDA /* CollectionSkeletonProtocol.swift in Sources */,
|
||||
F5307E2C1FAF6BC900EE67C5 /* SkeletonGradient.swift in Sources */,
|
||||
F587FB86202CEC95002DB5FE /* UIView+UIApplicationDelegate.swift in Sources */,
|
||||
F5F899EB1FAB9DA3002E8FDA /* SkeletonCollectionDataSource.swift in Sources */,
|
||||
F5F622411FAC6E31007C062A /* UIColor+Skeleton.swift in Sources */,
|
||||
F587FB84202CBFC8002DB5FE /* SkeletonFlow.swift in Sources */,
|
||||
F5F899D21FAB9630002E8FDA /* AssociationPolicy.swift in Sources */,
|
||||
F54CF5E62024CEB000330B0D /* UICollectionView+CollectionSkeleton.swift in Sources */,
|
||||
F56B94461FAE20AF0095662F /* PrepareForSkeletonProtocol.swift in Sources */,
|
||||
F5307E391FB1078E00EE67C5 /* SkeletonUICollectionViewDataSource.swift in Sources */,
|
||||
F5307E391FB1078E00EE67C5 /* SkeletonCollectionViewDataSource.swift in Sources */,
|
||||
F5307E3B1FB123C100EE67C5 /* ContainsMultilineText.swift in Sources */,
|
||||
F5F899E91FAB9D2B002E8FDA /* SkeletonLayer.swift in Sources */,
|
||||
F5307E2E1FB0E5E400EE67C5 /* UIView+Frame.swift in Sources */,
|
||||
@@ -375,6 +386,7 @@
|
||||
F5F899F71FABA607002E8FDA /* ViewController.swift in Sources */,
|
||||
F5F899F51FABA607002E8FDA /* AppDelegate.swift in Sources */,
|
||||
F5F622451FACA338007C062A /* Cell.swift in Sources */,
|
||||
88DEA97F1FCDBD78006C80EF /* Constants.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -523,7 +535,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = PTS5FAP7XL;
|
||||
DEVELOPMENT_TEAM = KWEMDK92F4;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
@@ -548,7 +560,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = PTS5FAP7XL;
|
||||
DEVELOPMENT_TEAM = KWEMDK92F4;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
@@ -576,7 +588,7 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = PTS5FAP7XL;
|
||||
DEVELOPMENT_TEAM = KWEMDK92F4;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Configs/SkeletonViewExampleInfo.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
@@ -601,7 +613,7 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = PTS5FAP7XL;
|
||||
DEVELOPMENT_TEAM = KWEMDK92F4;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Configs/SkeletonViewExampleInfo.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0910"
|
||||
LastUpgradeVersion = "0920"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -28,5 +28,5 @@ extension CollectionSkeleton where Self: UIScrollView {
|
||||
func removeDummyDataSource(reloadAfter: Bool) {}
|
||||
func disableScrolling() { isScrollEnabled = false }
|
||||
func enableScrolling() { isScrollEnabled = true }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ public typealias ReusableCellIdentifier = String
|
||||
class SkeletonCollectionDataSource: NSObject {
|
||||
|
||||
weak var originalTableViewDataSource: SkeletonTableViewDataSource?
|
||||
weak var originalCollectionViewDataSource: UICollectionViewDataSource?
|
||||
weak var originalCollectionViewDataSource: SkeletonCollectionViewDataSource?
|
||||
var rowHeight: CGFloat = 0.0
|
||||
|
||||
convenience init(tableViewDataSource: SkeletonTableViewDataSource? = nil, collectionViewDataSource: UICollectionViewDataSource? = nil, rowHeight: CGFloat = 0.0) {
|
||||
convenience init(tableViewDataSource: SkeletonTableViewDataSource? = nil, collectionViewDataSource: SkeletonCollectionViewDataSource? = nil, rowHeight: CGFloat = 0.0) {
|
||||
self.init()
|
||||
self.originalTableViewDataSource = tableViewDataSource
|
||||
self.originalCollectionViewDataSource = collectionViewDataSource
|
||||
@@ -40,20 +40,24 @@ extension SkeletonCollectionDataSource: UITableViewDataSource {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
|
||||
return cell
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - [WIP] UICollectionViewDataSource
|
||||
// MARK: - UICollectionViewDataSource
|
||||
extension SkeletonCollectionDataSource: UICollectionViewDataSource {
|
||||
|
||||
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
return 1
|
||||
return originalCollectionViewDataSource?.numSections(in: collectionView) ?? 0
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return 4
|
||||
return originalCollectionViewDataSource?.collectionSkeletonView(collectionView, numberOfItemsInSection: section) ?? 0
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
return UICollectionViewCell()
|
||||
let cellIdentifier = originalCollectionViewDataSource?.collectionSkeletonView(collectionView, cellIdentifierForItemAt: indexPath) ?? ""
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath)
|
||||
return cell
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// SkeletonUICollectionViewDataSource.swift
|
||||
// SkeletonView-iOS
|
||||
//
|
||||
// Created by Juanpe Catalán on 06/11/2017.
|
||||
// Copyright © 2017 SkeletonView. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
public protocol SkeletonCollectionViewDataSource: UICollectionViewDataSource {
|
||||
func numSections(in collectionSkeletonView: UICollectionView) -> Int
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier
|
||||
}
|
||||
|
||||
public extension SkeletonCollectionViewDataSource {
|
||||
|
||||
func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return skeletonView.estimatedNumberOfRows
|
||||
}
|
||||
|
||||
func numSections(in collectionSkeletonView: UICollectionView) -> Int { return 1 }
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
//
|
||||
// SkeletonUICollectionViewDataSource.swift
|
||||
// SkeletonView-iOS
|
||||
//
|
||||
// Created by Juanpe Catalán on 06/11/2017.
|
||||
// Copyright © 2017 SkeletonView. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
// Work in progress
|
||||
protocol SkeletonUICollectionViewDataSource: UICollectionViewDataSource {}
|
||||
@@ -10,8 +10,34 @@ import UIKit
|
||||
|
||||
extension UICollectionView: CollectionSkeleton {
|
||||
|
||||
var estimatedNumberOfRows: Int {
|
||||
guard let flowlayout = collectionViewLayout as? UICollectionViewFlowLayout else { return 0 }
|
||||
return Int(ceil(frame.height/flowlayout.itemSize.height))
|
||||
}
|
||||
|
||||
var skeletonDataSource: SkeletonCollectionDataSource? {
|
||||
get { return objc_getAssociatedObject(self, &DataSourceAssociatedKeys.dummyDataSource) as? SkeletonCollectionDataSource }
|
||||
set { objc_setAssociatedObject(self, &DataSourceAssociatedKeys.dummyDataSource, newValue, AssociationPolicy.retain.objc) }
|
||||
set {
|
||||
objc_setAssociatedObject(self, &DataSourceAssociatedKeys.dummyDataSource, newValue, AssociationPolicy.retain.objc)
|
||||
self.dataSource = newValue
|
||||
}
|
||||
}
|
||||
|
||||
func addDummyDataSource() {
|
||||
guard let originalDataSource = self.dataSource as? SkeletonCollectionViewDataSource,
|
||||
!(originalDataSource is SkeletonCollectionDataSource)
|
||||
else { return }
|
||||
|
||||
let dataSource = SkeletonCollectionDataSource(collectionViewDataSource: originalDataSource, rowHeight: 0.0)
|
||||
self.skeletonDataSource = dataSource
|
||||
reloadData()
|
||||
}
|
||||
|
||||
func removeDummyDataSource(reloadAfter: Bool) {
|
||||
guard let dataSource = self.dataSource as? SkeletonCollectionDataSource else { return }
|
||||
self.skeletonDataSource = nil
|
||||
self.dataSource = dataSource.originalCollectionViewDataSource
|
||||
if reloadAfter { self.reloadData() }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,12 +74,12 @@ public extension CALayer {
|
||||
|
||||
var sliding: CAAnimation {
|
||||
let startPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.startPoint))
|
||||
startPointAnim.fromValue = NSValue(cgPoint:CGPoint(x: -1, y: 0.5))
|
||||
startPointAnim.toValue = NSValue(cgPoint:CGPoint(x:1, y: 0.5))
|
||||
startPointAnim.fromValue = CGPoint(x: -1, y: 0.5)
|
||||
startPointAnim.toValue = CGPoint(x:1, y: 0.5)
|
||||
|
||||
let endPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.endPoint))
|
||||
endPointAnim.fromValue = NSValue(cgPoint:CGPoint(x: 0, y: 0.5))
|
||||
endPointAnim.toValue = NSValue(cgPoint:CGPoint(x:2, y: 0.5))
|
||||
endPointAnim.fromValue = CGPoint(x: 0, y: 0.5)
|
||||
endPointAnim.toValue = CGPoint(x:2, y: 0.5)
|
||||
|
||||
let animGroup = CAAnimationGroup()
|
||||
animGroup.animations = [startPointAnim, endPointAnim]
|
||||
|
||||
@@ -12,6 +12,8 @@ private enum AssociatedKeys {
|
||||
static var skeletonable = "skeletonable"
|
||||
static var status = "status"
|
||||
static var skeletonLayer = "layer"
|
||||
static var flowDelegate = "flowDelegate"
|
||||
static var isSkeletonAnimated = "isSkeletonAnimated"
|
||||
}
|
||||
|
||||
public extension UIView {
|
||||
@@ -34,6 +36,11 @@ extension UIView {
|
||||
case off
|
||||
}
|
||||
|
||||
var flowDelegate: SkeletonFlowDelegate? {
|
||||
get { return objc_getAssociatedObject(self, &AssociatedKeys.flowDelegate) as? SkeletonFlowDelegate }
|
||||
set { objc_setAssociatedObject(self, &AssociatedKeys.flowDelegate, newValue, AssociationPolicy.retain.objc) }
|
||||
}
|
||||
|
||||
var skeletonLayer: SkeletonLayer? {
|
||||
get { return objc_getAssociatedObject(self, &AssociatedKeys.skeletonLayer) as? SkeletonLayer }
|
||||
set { objc_setAssociatedObject(self, &AssociatedKeys.skeletonLayer, newValue, AssociationPolicy.retain.objc) }
|
||||
@@ -43,6 +50,11 @@ extension UIView {
|
||||
get { return objc_getAssociatedObject(self, &AssociatedKeys.status) as? Status ?? .off }
|
||||
set { objc_setAssociatedObject(self, &AssociatedKeys.status, newValue, AssociationPolicy.retain.objc) }
|
||||
}
|
||||
|
||||
var skeletonIsAnimated: Bool! {
|
||||
get { return objc_getAssociatedObject(self, &AssociatedKeys.isSkeletonAnimated) as? Bool ?? false }
|
||||
set { objc_setAssociatedObject(self, &AssociatedKeys.isSkeletonAnimated, newValue, AssociationPolicy.retain.objc) }
|
||||
}
|
||||
|
||||
fileprivate var skeletonable: Bool! {
|
||||
get { return objc_getAssociatedObject(self, &AssociatedKeys.skeletonable) as? Bool ?? false }
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// UIView+UIApplicationDelegate.swift
|
||||
// SkeletonView-iOS
|
||||
//
|
||||
// Created by Juanpe Catalán on 08/02/2018.
|
||||
// Copyright © 2018 SkeletonView. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIView {
|
||||
|
||||
enum Constants {
|
||||
static let becomeActiveNotification = NSNotification.Name.UIApplicationDidBecomeActive
|
||||
static let enterForegroundNotification = NSNotification.Name.UIApplicationDidEnterBackground
|
||||
static let needAnimatedSkeletonKey = "needAnimateSkeleton"
|
||||
}
|
||||
|
||||
func addAppNotificationsObservers() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: Constants.becomeActiveNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: Constants.enterForegroundNotification, object: nil)
|
||||
}
|
||||
|
||||
func removeAppNoticationsObserver() {
|
||||
NotificationCenter.default.removeObserver(self, name: Constants.becomeActiveNotification, object: nil)
|
||||
NotificationCenter.default.removeObserver(self, name: Constants.enterForegroundNotification, object: nil)
|
||||
}
|
||||
|
||||
@objc func appDidBecomeActive() {
|
||||
if UserDefaults.standard.bool(forKey: Constants.needAnimatedSkeletonKey) {
|
||||
startSkeletonAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func appDidEnterBackground() {
|
||||
UserDefaults.standard.set((isSkeletonActive && skeletonIsAnimated), forKey: Constants.needAnimatedSkeletonKey)
|
||||
}
|
||||
}
|
||||
@@ -66,12 +66,12 @@ public class SkeletonAnimationBuilder {
|
||||
return { layer in
|
||||
|
||||
let startPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.startPoint))
|
||||
startPointAnim.fromValue = NSValue(cgPoint: direction.startPoint.from)
|
||||
startPointAnim.toValue = NSValue(cgPoint: direction.startPoint.to)
|
||||
startPointAnim.fromValue = direction.startPoint.from
|
||||
startPointAnim.toValue = direction.startPoint.to
|
||||
|
||||
let endPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.endPoint))
|
||||
endPointAnim.fromValue = NSValue(cgPoint: direction.endPoint.from)
|
||||
endPointAnim.toValue = NSValue(cgPoint: direction.endPoint.to)
|
||||
endPointAnim.fromValue = direction.endPoint.from
|
||||
endPointAnim.toValue = direction.endPoint.to
|
||||
|
||||
let animGroup = CAAnimationGroup()
|
||||
animGroup.animations = [startPointAnim, endPointAnim]
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// SkeletonFlow.swift
|
||||
// SkeletonView-iOS
|
||||
//
|
||||
// Created by Juanpe Catalán on 08/02/2018.
|
||||
// Copyright © 2018 SkeletonView. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol SkeletonFlowDelegate {
|
||||
func willBeginShowingSkeletons(withRootView rootView: UIView)
|
||||
func willBeginHidingSkeletons(withRootView rootView: UIView)
|
||||
}
|
||||
|
||||
class SkeletonFlowHandler: SkeletonFlowDelegate {
|
||||
|
||||
func willBeginShowingSkeletons(withRootView rootView: UIView) {
|
||||
rootView.addAppNotificationsObservers()
|
||||
}
|
||||
|
||||
func willBeginHidingSkeletons(withRootView rootView: UIView) {
|
||||
rootView.removeAppNoticationsObserver()
|
||||
rootView.flowDelegate = nil
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
|
||||
class SkeletonLayerFactory {
|
||||
|
||||
func makeLayer(withType type: SkeletonType, usingColors colors: [UIColor], andHolder holder: UIView) -> SkeletonLayer {
|
||||
func makeSkeletonLayer(withType type: SkeletonType, usingColors colors: [UIColor], andHolder holder: UIView) -> SkeletonLayer {
|
||||
return SkeletonLayer(withType: type, usingColors: colors, andSkeletonHolder: holder)
|
||||
}
|
||||
|
||||
|
||||
+37
-11
@@ -27,16 +27,12 @@ public extension UIView {
|
||||
}
|
||||
|
||||
func hideSkeleton(reloadDataAfter reload: Bool = true) {
|
||||
removeDummyDataSourceIfNeeded(reloadAfter: reload)
|
||||
isUserInteractionEnabled = true
|
||||
recursiveSearch(inArray: subviewsSkeletonables,
|
||||
leafBlock: { removeSkeletonLayer() },
|
||||
recursiveBlock: {
|
||||
$0.hideSkeleton(reloadDataAfter: reload)
|
||||
})
|
||||
flowDelegate?.willBeginHidingSkeletons(withRootView: self)
|
||||
recursiveHideSkeleton(reloadDataAfter: reload)
|
||||
}
|
||||
|
||||
func startSkeletonAnimation(_ anim: SkeletonLayerAnimation? = nil) {
|
||||
skeletonIsAnimated = true
|
||||
recursiveSearch(inArray: subviewsSkeletonables,
|
||||
leafBlock: startSkeletonLayerAnimationBlock(anim)) {
|
||||
$0.startSkeletonAnimation(anim)
|
||||
@@ -44,6 +40,7 @@ public extension UIView {
|
||||
}
|
||||
|
||||
func stopSkeletonAnimation() {
|
||||
skeletonIsAnimated = false
|
||||
recursiveSearch(inArray: subviewsSkeletonables,
|
||||
leafBlock: stopSkeletonLayerAnimationBlock) {
|
||||
$0.stopSkeletonAnimation()
|
||||
@@ -54,6 +51,12 @@ public extension UIView {
|
||||
extension UIView {
|
||||
|
||||
func showSkeleton(withType type: SkeletonType = .solid, usingColors colors: [UIColor], animated: Bool = false, animation: SkeletonLayerAnimation? = nil) {
|
||||
flowDelegate = SkeletonFlowHandler()
|
||||
flowDelegate?.willBeginShowingSkeletons(withRootView: self)
|
||||
recursiveShowSkeleton(withType: type, usingColors: colors, animated: animated, animation: animation)
|
||||
}
|
||||
|
||||
fileprivate func recursiveShowSkeleton(withType type: SkeletonType = .solid, usingColors colors: [UIColor], animated: Bool = false, animation: SkeletonLayerAnimation? = nil) {
|
||||
addDummyDataSourceIfNeeded()
|
||||
recursiveSearch(inArray: subviewsSkeletonables,
|
||||
leafBlock: {
|
||||
@@ -61,9 +64,20 @@ extension UIView {
|
||||
isUserInteractionEnabled = false
|
||||
(self as? PrepareForSkeleton)?.prepareViewForSkeleton()
|
||||
addSkeletonLayer(withType: type, usingColors: colors, animated: animated, animation: animation)
|
||||
}) {
|
||||
$0.showSkeleton(withType: type, usingColors: colors, animated: animated, animation: animation)
|
||||
}
|
||||
}) {
|
||||
$0.recursiveShowSkeleton(withType: type, usingColors: colors, animated: animated, animation: animation)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func recursiveHideSkeleton(reloadDataAfter reload: Bool = true) {
|
||||
removeDummyDataSourceIfNeeded()
|
||||
isUserInteractionEnabled = true
|
||||
recursiveSearch(inArray: subviewsSkeletonables,
|
||||
leafBlock: {
|
||||
removeSkeletonLayer()
|
||||
}, recursiveBlock: {
|
||||
$0.recursiveHideSkeleton(reloadDataAfter: reload)
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func startSkeletonLayerAnimationBlock(_ anim: SkeletonLayerAnimation? = nil) -> VoidBlock {
|
||||
@@ -99,6 +113,18 @@ extension UITableViewCell {
|
||||
}
|
||||
}
|
||||
|
||||
extension UICollectionView {
|
||||
override var subviewsSkeletonables: [UIView] {
|
||||
return subviews.filter { $0.isSkeletonable }
|
||||
}
|
||||
}
|
||||
|
||||
extension UICollectionViewCell {
|
||||
override var subviewsSkeletonables: [UIView] {
|
||||
return contentView.subviews.filter { $0.isSkeletonable }
|
||||
}
|
||||
}
|
||||
|
||||
extension UIStackView {
|
||||
override var subviewsSkeletonables: [UIView] {
|
||||
return arrangedSubviews.filter { $0.isSkeletonable }
|
||||
@@ -108,7 +134,7 @@ extension UIStackView {
|
||||
extension UIView {
|
||||
|
||||
func addSkeletonLayer(withType type: SkeletonType, usingColors colors: [UIColor], gradientDirection direction: GradientDirection? = nil, animated: Bool, animation: SkeletonLayerAnimation? = nil) {
|
||||
self.skeletonLayer = SkeletonLayerFactory().makeLayer(withType: type, usingColors: colors, andHolder: self)
|
||||
self.skeletonLayer = SkeletonLayerFactory().makeSkeletonLayer(withType: type, usingColors: colors, andHolder: self)
|
||||
layer.insertSublayer(skeletonLayer!.contentLayer, at: UInt32.max)
|
||||
if animated { skeletonLayer!.start(animation) }
|
||||
status = .on
|
||||
|
||||
Reference in New Issue
Block a user