![](../Assets/header2.jpg)

codebeat badge SkeletonView Playground
Twitter: @JuanpeCatalan PayPal Licence

**🌎 Traductions: [🇬🇧](../README.md) . [🇨🇳](README_zh.md) . [🇧🇷](README_pt-br.md) . [🇰🇷](README_ko.md) . [🇫🇷](README_fr.md) . [🇩🇪](README_de.md)** 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](#-caractéristiques) - [🎬 Guides](#-guides) - [📲 Installation](#-installation) - [Utilisation de CocoaPods](#utilisation-de-cocoapods) - [Utilisation de Carthage](#utilisation-de-carthage) - [Utilisation du gestionnaire de paquets Swift](#utilisation-du-gestionnaire-de-paquets-swift) - [🐒 Mode d'emploi](#-mode-demploi) - [Extra](#extra) - [Mise en page des vues squelettes](#mise-en-page-des-vues-squelettes) - [Mise à jour de la configuration du squelette](#mise-à-jour-de-la-configuration-du-squelette) - [🌿 Collections](#-collections) - [UITableView](#uitableview) - [UICollectionView](#uicollectionview) - [📰 Texte multiligne](#-texte-multiligne) - [🎛 Personnaliser](#-personnaliser) - [🎨 Couleurs personnalisées](#-couleurs-personnalisées) - [Image tirée du site web https://flatuicolors.com](#image-tirée-du-site-web-httpsflatuicolorscom) - [🦋 Présentation](#-présentation) - [🤓 Animations personnalisées](#-animations-personnalisées) - [🏄 Transitions](#-transitions) - [👨👧👦 Hiérarchie](#-hiérarchie) - [🔬 Débugger](#-débugger) - [📚 Documentation](#-documentation) - [📋 Versions OS et SDK supportées](#-versions-os-et-sdk-supportées) - [📬 Prochaines étapes](#-prochaines-étapes) - [❤️ Contribuer](#️-contribuer) - [Projet généré avec SwiftPlate](#projet-généré-avec-swiftplate) - [📢 Mentions](#-mentions) - [👨🏻‍💻 Auteur](#-auteur) - [👮🏻 Licence](#-licence) ## 🌟 Caractéristiques - [x] Facile à utiliser - [x] Tous les UIViews sont squelettisables - [x] Entièrement personnalisable - [x] Universel (iPhone et iPad) - [x] Interface Builder friendly - [x] Syntaxe Swift simple - [x] Base de code légère et lisible ## 🎬 Guides [](https://youtu.be/75kgOhWsPNA) ## 📲 Installation #### Utilisation de [CocoaPods](https://cocoapods.org) Editez votre "podfile" et spécifiez la dépendance: ```ruby pod "SkeletonView" ``` #### Utilisation de [Carthage](https://github.com/carthage) Modifiez votre "Cartfile" et spécifiez la dépendance: ```bash github "Juanpe/SkeletonView" ``` #### Utilisation du [gestionnaire de paquets Swift](https://github.com/apple/swift-package-manager) 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`. ```swift dependencies: [ .package(url: "https://github.com/Juanpe/SkeletonView.git", from: "1.7.0") ] ``` ## 🐒 Mode d'emploi Seulement **3** étapes nécessaires pour utiliser `SkeletonView` : **1.** Importer SkeletonView au bon endroit. ```swift import SkeletonView ``` **2.** Maintenant, définissez les vues qui seront `squelettisables`. Vous y arrivez de deux façons : **En utilisant du code:** ```swift avatarImageView.isSkeletonable = true ``` **Utilisation des IB/Storyboards:** ![](../Assets/storyboard.png) **Une fois que vous avez défini les vues, vous pouvez montrer le **squelette**. Pour le faire, vous avez quatre choix : ```swift (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éthode `show` dans la vue principale du conteneur. Par exemple, avec UIViewControllers ### Extra #### Mise en page des vues squelettes 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 : ```swift override func viewDidLayoutSubviews() { view.layoutSkeletonIfNeeded() } ``` ⚠️⚠️ Vous ne devriez pas appeler cette méthode. À partir de la *version 1.8.1*, vous n'avez pas besoin d'appeler cette méthode, la bibliothèque le fait automatiquement. Vous pouvez donc utiliser cette méthode *seulement* dans les cas où vous devez mettre à jour manuellement la présentation du squelette. #### Mise à jour de la configuration du squelette Vous pouvez modifier la configuration du squelette à tout moment comme sa couleur, son animation, etc : ```swift (1) view.updateSkeleton() // Solide (2) view.updateGradientSkeleton() // Gradient (3) view.updateAnimatedSkeleton() // Solid animated (4) view.updateAnimatedGradientSkeleton() // Gradient animé ``` ### 🌿 Collections Maintenant, `SkeletonView` est compatible avec `UITableView` et `UICollectionView`. #### UITableView Si vous voulez montrer le squelette dans un `UITableView`, vous devez vous conformer au protocole `SkeletonTableViewDataSource`. ``` swift 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: ``` swift func numSections(in collectionSkeletonView: UITableView) -> Int // Par défaut: 1 ``` ``` swift 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 ``` ``` swift func collectionSkeletonView(_ skeletonView: UITableView, identifierForHeaderInSection section: Int) -> ReusableHeaderFooterIdentifier? // Par défaut: nil ``` ``` swift 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 : ``` swift func collectionSkeletonView(_ skeletonView : UITableView, cellIdentifierForRowAt indexPath : IndexPath) -> ReusableCellIdentifier ``` **Exemple** ``` swift 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 la `estimatedRowHeight`. 👩🏼 **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` : ![](../Assets/tableview_scheme.png) 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`. #### UICollectionView Pour ```UICollectionView```, vous devez conformer le protocole `SkeletonCollectionViewDataSource`. ``` 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 } ``` Le reste du processus ressemble à une `UITableView`. ### 📰 Texte multiligne ![](../Assets/multilines2.png) 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. ##### 🎛 Personnaliser 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%` | ![](../Assets/multiline_lastline.png) | **Corner radius** des lignes. (**NEW**) | `0...10` | `0` | ![](../Assets/multiline_corner.png) Pour modifier le pourcentage ou le rayon **à l'aide du code**, définissez les propriétés : ``` swift descriptionTextView.lastLineFillPercent = 50 descriptionTextView.linesCornerRadius = 5 ``` Ou, si vous préférez, utilisez l'**IB/Storyboard** : ![](../Assets/multiline_customize.png) ### 🎨 Couleurs personnalisées 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** ``` swift 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** ``` swift 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 ...` ![](../Assets/flatcolors.png) ###### Image tirée du site web [https://flatuicolors.com](https://flatuicolors.com) ### 🦋 Présentation **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)* - **gradient** : SkeletonGradient - *défaut : `SkeletonGradient(baseColor : .skeletonDefault)`* - **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 : ``` swift SkeletonAppearance.default.multilineHeight = 20 SkeletonAppearance.default.tintColor = .green ``` ### 🤓 Animations personnalisées `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. ``` swift public typealias SkeletonLayerAnimation = (CALayer) -> CAAnimation ``` Vous pouvez appeler la fonction comme ceci : ```swift 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). ```swift // 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 | ![](../Assets/sliding_left_to_right.gif) | .rightLeft | ![](../Assets/sliding_right_to_left.gif) | .topBottom | ![](../Assets/sliding_top_to_bottom.gif) | .bottomTop | ![](../Assets/sliding_bottom_to_top.gif) | .topLeftBottomRight | ![](../Assets/sliding_topLeft_to_bottomRight.gif) | .bottomRightTopLeft | ![](../Assets/sliding_bottomRight_to_topLeft.gif) > **😉 TRICK!** Il existe une autre façon de créer des animations de glissement, en utilisant simplement ce raccourci : >>```let animation = GradientDirection.leftToRight.slidingAnimation()``` ### 🏄 Transitions `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 : ```swift 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
### 👨👧👦 Hiérarchie 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| |:-------:|:-------:| | | | | | | | | | || | | | | | | | ### 🔬 Débugger **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 : ```swift var skeletonDescription : String ``` La représentation du squelette ressemble à ceci : ![](../Assets/debug_description.png) En outre, vous pouvez activer le nouveau mode **debug**. Il suffit d'ajouter la variable d'environnement `SKELETON_DEBUG` et de l'activer. ![](../Assets/debug_mode.png) Ensuite, lorsque le squelette apparaît, vous pouvez voir la hiérarchie des vues dans la console Xcode.
Ouvrez pour voir un exemple de sortie
### 📚 Documentation Bientôt disponible...😅 ### 📋 Versions OS et SDK supportées * iOS 9.0+ * tvOS 9.0+ * Swift 5 ## 📬 Prochaines étapes * [x] Fixer le pourcentage de remplissage de la dernière ligne dans les éléments multilignes * [x] Ajout d'autres animations en dégradé * [x] Cellules redimensionnables prises en charge * [x] Compatible avec CollectionView * [x] Compatible avec tvOS * [x] Ajouter l'état de recouvrement * [x] Apparence personnalisée par défaut * [x] Mode de debuggage * [x] Ajouter des animations lorsqu'il montre/cache les squelettes * [ ] Compatible avec les collections personnalisées * [ ] Compatible avec MacOS et WatchOS ## ❤️ Contribuer Il s'agit d'un projet open source, alors n'hésitez pas à y contribuer. Comment ? - Ouvrez un [numéro](https://github.com/Juanpe/SkeletonView/issues/new). - Envoyez vos commentaires via [email](mailto://juanpecatalan.com). - Proposez vos propres correctifs, suggestions et ouvrez une `pull request` avec les changements. Voir [tous les contributeurs](https://github.com/Juanpe/SkeletonView/graphs/contributors) ###### Projet généré avec [SwiftPlate](https://github.com/JohnSundell/SwiftPlate) ## 📢 Mentions - [iOS Dev Weekly #327](https://iosdevweekly.com/issues/327#start) - [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)](https://medium.mybridge.co/30-amazing-ios-swift-libraries-for-the-past-year-v-2018-7cf15027eee9) - [AppCoda Weekly #44](http://digest.appcoda.com/issues/appcoda-weekly-issue-44-81899) - [iOS Cookies Newsletter #103](https://us11.campaign-archive.com/?u=cd1f3ed33c6527331d82107ba&id=48131a516d) - [Bulletin d'information sur les développements Swift #113](https://andybargh.com/swiftdevelopments-113/) - [iOS Goodies #204](http://ios-goodies.com/post/167557280951/week-204) - [Swift Weekly #96](http://digest.swiftweekly.com/issues/swift-weekly-issue-96-81759) - [CocoaControls](https://www.cocoacontrols.com/controls/skeletonview) - [Bulletin d'information Génial iOS #74](https://ios.libhunt.com/newsletter/74) - [Swift News #36](https://www.youtube.com/watch?v=mAGpsQiy6so) - [Meilleurs articles sur iOS, nouveaux outils et plus](https://medium.com/flawless-app-stories/best-ios-articles-new-tools-more-fcbe673e10d) ## 👨🏻‍💻 Auteur [1.1]: http://i.imgur.com/tXSoThF.png [1]: http://www.twitter.com/JuanpeCatalan * Juanpe Catalán [![alt text][1.1]][1] Buy me a coffee ## 👮🏻 Licence ``` 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. ```