🌎 Traductions: 🇬🇧 . 🇨🇳 . 🇧🇷 . 🇰🇷 . 🇫🇷 . 🇩🇪
Aujourd'hui, presque toutes les applications ont des processus asynchrones, tels que les requêtes Api, les processus de longue durée, etc. Et pendant que les processus fonctionnent, les développeurs affichent généralement une vue de chargement pour montrer aux utilisateurs que quelque chose se passe.
"SkeletonView" a été créé pour répondre à ce besoin, une manière élégante de montrer aux utilisateurs que quelque chose se passe et aussi de les préparer aux contenus qu'ils attendent.
Profitez-en! 🙂
- 🌟 Caractéristiques
- 🎬 Guides
- 📲 Installation
- 🐒 Mode d'emploi
- 📬 Prochaines étapes
- ❤️ Contribuer - Projet généré avec SwiftPlate
- 📢 Mentions
- 👨🏻💻 Auteur
- 👮🏻 Licence
- Facile à utiliser
- Tous les UIViews sont squelettisables
- Entièrement personnalisable
- Universel (iPhone et iPad)
- Interface Builder friendly
- Syntaxe Swift simple
- Base de code légère et lisible
Utilisation de CocoaPods
Editez votre "podfile" et spécifiez la dépendance:
pod "SkeletonView"
Utilisation de Carthage
Modifiez votre "Cartfile" et spécifiez la dépendance:
github "Juanpe/SkeletonView"
Utilisation du gestionnaire de paquets Swift
Une fois que vous avez configuré votre paquet Swift, ajouter SkeletonView
comme dépendance est aussi facile que de l'ajouter à la valeur des dépendances
de votre Package.swift
.
dependencies: [
.package(url: "https://github.com/Juanpe/SkeletonView.git", from: "1.7.0")
]
Seulement 3 étapes nécessaires pour utiliser SkeletonView
:
1. Importer SkeletonView au bon endroit.
import SkeletonView
2. Maintenant, définissez les vues qui seront squelettisables
. Vous y arrivez de deux façons :
En utilisant du code:
avatarImageView.isSkeletonable = true
Utilisation des IB/Storyboards:
**Une fois que vous avez défini les vues, vous pouvez montrer le squelette. Pour le faire, vous avez quatre choix :
(1) view.showSkeleton() // Solide
(2) view.showGradientSkeleton() // Gradient
(3) view.showAnimatedSkeleton() // Solide animé
(4) view.showAnimatedGradientSkeleton() // Gradient animé
Preview
Solide | Gradient | Animé Solide | Animé Gradient |
IMPORTANT!
SkeletonView
est récursif, donc si vous voulez montrer le squelette dans toutes les vues squelettables, il vous suffit d'appeler la méthodeshow
dans la vue principale du conteneur. Par exemple, avec UIViewControllers
Il arrive que le squelette ne corresponde pas à votre mise en page parce que les limites de la vue parent ont changé. Par exemple, la rotation de l'appareil.
Vous pouvez relayer les vues du squelette de cette manière :
override func viewDidLayoutSubviews() {
view.layoutSkeletonIfNeeded()
}
Vous pouvez modifier la configuration du squelette à tout moment comme sa couleur, son animation, etc :
(1) view.updateSkeleton() // Solide
(2) view.updateGradientSkeleton() // Gradient
(3) view.updateAnimatedSkeleton() // Solid animated
(4) view.updateAnimatedGradientSkeleton() // Gradient animé
Maintenant, SkeletonView
est compatible avec UITableView
et UICollectionView
.
Si vous voulez montrer le squelette dans un UITableView
, vous devez vous conformer au protocole SkeletonTableViewDataSource
.
public protocol SkeletonTableViewDataSource: UITableViewDataSource {
func numSections(in collectionSkeletonView: UITableView) -> Int
func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int
func collectionSkeletonView(_ skeletonView: UITableView, cellIdentifierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier
func collectionSkeletonView(_ skeletonView: UITableView, identifierForHeaderInSection section: Int) -> ReusableHeaderFooterIdentifier?
func collectionSkeletonView(_ skeletonView: UITableView, identifierForFooterInSection section: Int) -> ReusableHeaderFooterIdentifier?
}
Comme vous pouvez le voir, ce protocole hérite de UITableViewDataSource
, vous pouvez donc remplacer ce protocole par le protocole squelette.
Ce protocole a une implémentation par défaut:
func numSections(in collectionSkeletonView: UITableView) -> Int
// Par défaut: 1
func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int
// Par défaut:
// Il calcule le nombre de cellules nécessaires pour remplir l'ensemble du tableau
func collectionSkeletonView(_ skeletonView: UITableView, identifierForHeaderInSection section: Int) -> ReusableHeaderFooterIdentifier?
// Par défaut: nil
func collectionSkeletonView(_ skeletonView: UITableView, identifierForFooterInSection section: Int) -> ReusableHeaderFooterIdentifier?
// Par défaut: nil
Il n'y a qu'une seule méthode à mettre en œuvre pour faire connaître au Squelette l'identifiant de la cellule. Cette méthode n'a pas d'implémentation par défaut :
func collectionSkeletonView(_ skeletonView : UITableView, cellIdentifierForRowAt indexPath : IndexPath) -> ReusableCellIdentifier
Exemple
func collectionSkeletonView(_ skeletonView : UITableView, cellIdentifierForRowAt indexPath : IndexPath) -> ReusableCellIdentifier {
return "CellIdentifier".
}
IMPORTANT! Si vous utilisez des cellules redimensionnables (
tableView.rowHeight = UITableViewAutomaticDimension
), il est obligatoire de définir laestimatedRowHeight
.
👩🏼 **Comment préciser quels éléments sont squelettisables ?
Voici une illustration qui montre comment vous devez spécifier quels éléments sont squelettisables lorsque vous utilisez une UITableView
:
Comme vous pouvez le voir, nous devons faire skeletonable
la tableview, la cellule et les éléments de l'interface visuelle, mais nous n'avons pas besoin de faire skeletonable
le contentView
.
Pour UICollectionView
, vous devez conformer le protocole SkeletonCollectionViewDataSource
.
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
}
Le reste du processus ressemble à une UITableView
.
Lorsqu'on utilise des éléments avec du texte, SkeletonView
dessine des lignes pour simuler le texte.
En outre, vous pouvez décider combien de lignes vous voulez. Si numberOfLines
est réglé à zéro, il calculera le combien de lignes sont nécessaires pour remplir tout le squelette et il sera dessiné. Au contraire, si vous le réglez sur un, deux ou tout autre nombre supérieur à zéro, il ne dessinera que ce nombre de lignes.
Vous pouvez définir certaines propriétés pour les éléments multilignes.
Propriété | Valeurs | Par défaut | Aperçu |
---|---|---|---|
Pourcentage de remplissage de la dernière ligne. | 0...100 |
70% |
|
Corner radius des lignes. (NEW) | 0...10 |
0 |
Pour modifier le pourcentage ou le rayon à l'aide du code, définissez les propriétés :
descriptionTextView.lastLineFillPercent = 50
descriptionTextView.linesCornerRadius = 5
Ou, si vous préférez, utilisez l'IB/Storyboard :
Vous pouvez décider la couleur du squelette. Il vous suffit de passer comme paramètre la couleur ou le gradient que vous souhaitez.
Utiliser des couleurs solides
view.showSkeleton(usingColor : UIColor.gray) // Solide
// ou
view.showSkeleton(usingColor : UIColor(red : 25.0, green : 30.0, blue : 255.0, alpha : 1.0))
Utilisation des gradients
let gradient = SkeletonGradient(baseColor : UIColor.midnightBlue)
view.showGradientSkeleton(usingGradient : gradient) // Gradient
En outre, SkeletonView
dispose de 20 couleurs unies 🤙🏼
UIColor.turquoise, UIColor.greenSea, UIColor.sunFlower, UIColor.flatOrange ...
Image tirée du site web https://flatuicolors.com
NOUVEAU Les squelettes ont une apparence par défaut. Ainsi, lorsque vous ne spécifiez pas la couleur, le gradient ou les propriétés multilignes, SkeletonView
utilise les valeurs par défaut.
Valeurs par défaut :
- tintColor : UIColor
- défaut :
.skeletonDefault
(comme.clouds
mais adaptable au thème sombre)
- défaut :
- gradient : SkeletonGradient
- défaut :
SkeletonGradient(baseColor : .skeletonDefault)
- défaut :
- multilineHeight : CGFloat
- défaut : 15
- multilineSpacing : CGFloat
- défaut : 10
- multilineLastLineFillPercent : Int
- défaut : 70
- multilineCornerRadius : Int
- défaut : 0
- skeletonCornerRadius : CGFloat (IBInspectable) (Faites votre vue squelette avec des coins)
- défaut : 0
Pour obtenir ces valeurs par défaut, vous pouvez utiliser SkeletonAppearance.default
. En utilisant cette propriété, vous pouvez également définir les valeurs :
SkeletonAppearance.default.multilineHeight = 20
SkeletonAppearance.default.tintColor = .green
SkeletonView
a deux animations intégrées, pulse pour les squelettes solides et sliding pour les gradients.
De plus, si vous voulez faire votre propre animation de squelette, c'est très facile.
Skeleton fournit la fonction showAnimatedSkeleton
qui possède une fermeture SkeletonLayerAnimation
où vous pouvez définir votre animation personnalisée.
public typealias SkeletonLayerAnimation = (CALayer) -> CAAnimation
Vous pouvez appeler la fonction comme ceci :
view.showAnimatedSkeleton { (layer) -> CAAnimation in
let animation = CAAnimation()
// Personnalisez ici votre animation
return animation
}
SkeletonAnimationBuilder
est disponible. C'est un constructeur pour faire SkeletonLayerAnimation
.
Aujourd'hui, vous pouvez créer des animations glissantes pour les gradients, en décidant de la direction et en fixant la durée de l'animation (par défaut = 1,5s).
// func makeSlidingAnimation(withDirection direction : GradientDirection, duration : CFTimeInterval = 1.5) -> SkeletonLayerAnimation
let animation = SkeletonAnimationBuilder().makeSlidingAnimation(withDirection : .leftToRight)
view.showAnimatedGradientSkeleton(usingGradient : gradient, animation : animation)
GradientDirection
est une enum
, avec ces cas :
Direction | Aperçu |
---|---|
.leftRight | |
.rightLeft | |
.topBottom | |
.bottomTop | |
.topLeftBottomRight | |
.bottomRightTopLeft |
😉 TRICK! Il existe une autre façon de créer des animations de glissement, en utilisant simplement ce raccourci :
let animation = GradientDirection.leftToRight.slidingAnimation()
SkeletonView
a des transitions intégrées pour montrer ou cacher les squelettes d'une manière lisse 🤙
Pour utiliser la transition, il suffit d'ajouter le paramètre "transition" à votre fonction showSkeleton()
ou hideSkeleton()
avec le temps de transition, comme ceci :
view.showSkeleton(transition : .crossDissolve(0.25)) //Montrer la transition de dissolution croisée du squelette avec un temps de fondu de 0,25 seconde
view.hideSkeleton(transition : .crossDissolve(0.25)) //Cachez la transition de dissolution croisée du squelette avec un temps de fondu de 0,25 seconde
La valeur par défaut est crossDissolve(0.25)
.
Preview
None | Cross dissolve |
Puisque SkeletonView
est récursif, et que nous voulons que le squelette soit très efficace, nous voulons arrêter la récursivité dès que possible. Pour cette raison, vous devez définir la vue du conteneur comme Skeletonable
, parce que Skeleton arrêtera de chercher des sous-vues squelettisables
dès qu'une vue n'est pas Skeletonable
, cassant alors la récursivité.
Parce qu'une image vaut mille mots :
Dans cet exemple, nous avons un UIViewController
avec une ContainerView
et une UITableView
. Lorsque la vue est prête, nous montrons le squelette en utilisant cette méthode :
view.showSkeleton()
isSkeletonable
= ☠️
Configuration | Résultat |
---|---|
NOUVEAU Afin de faciliter les tâches de debuggage lorsque quelque chose ne fonctionne pas bien. SkeletonView
a de nouveaux outils.
Tout d'abord, UIView
a une nouvelle propriété disponible avec son squelette d'information :
var skeletonDescription : String
La représentation du squelette ressemble à ceci :
En outre, vous pouvez activer le nouveau mode debug. Il suffit d'ajouter la variable d'environnement SKELETON_DEBUG
et de l'activer.
Ensuite, lorsque le squelette apparaît, vous pouvez voir la hiérarchie des vues dans la console Xcode.
Bientôt disponible...😅
- iOS 9.0+
- tvOS 9.0+
- Swift 5
- Fixer le pourcentage de remplissage de la dernière ligne dans les éléments multilignes
- Ajout d'autres animations en dégradé
- Cellules redimensionnables prises en charge
- Compatible avec CollectionView
- Compatible avec tvOS
- Ajouter l'état de recouvrement
- Apparence personnalisée par défaut
- Mode de debuggage
- Ajouter des animations lorsqu'il montre/cache les squelettes
- Compatible avec les collections personnalisées
- Compatible avec MacOS et WatchOS
Il s'agit d'un projet open source, alors n'hésitez pas à y contribuer. Comment ?
- Ouvrez un numéro.
- Envoyez vos commentaires via email.
- Proposez vos propres correctifs, suggestions et ouvrez une
pull request
avec les changements.
Projet généré avec SwiftPlate
- iOS Dev Weekly #327
- [Hacking with Swift Articles] (https://www.hackingwithswift.com/articles/40/skeletonview-makes-loading-content-beautiful)
- [Top 10 articles Swift de novembre] (https://medium.mybridge.co/swift-top-10-articles-for-the-past-month-v-nov-2017-dfed7861cd65)
- 30 bibliothèques incroyables pour iOS Swift (v2018)
- AppCoda Weekly #44
- iOS Cookies Newsletter #103
- Bulletin d'information sur les développements Swift #113
- iOS Goodies #204
- Swift Weekly #96
- CocoaControls
- Bulletin d'information Génial iOS #74
- Swift News #36
- Meilleurs articles sur iOS, nouveaux outils et plus
MIT License
Copyright (c) 2017 Juanpe Catalán
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.