Recursos • Guias • Instalação • Uso • Diversos • Contribuindo
? ReadMe está disponível em outros idiomas: ?? . ? . ? . ? . ? . ?
Hoje, quase todos os aplicativos possuem processos assíncronos, como solicitações de API, processos de longa execução etc. Enquanto os processos estão funcionando, geralmente os desenvolvedores colocam uma visão de carregamento para mostrar aos usuários que algo está acontecendo.
O SkeletonView foi concebido para atender a essa necessidade, uma maneira elegante de mostrar aos usuários que algo está acontecendo e também prepará -los para os quais o conteúdo está esperando.
Apreciá-lo! ?
| Guias de SkeletonView - Primeiro começando | Como criar uma visão de carregamento com vista para o esqueleto no Swift 5.2 por ikh4ever studio | Crie Visualização de Carregamento do Esqueleto no App (Swift 5) - Xcode 11, 2020 pela IOS Academy | Cómo Crear Una Animación de Carga de Datos En ios por MUREDEV |
pod 'SkeletonView' github "Juanpe/SkeletonView"dependencies: [
. package ( url : " https://github.com/Juanpe/SkeletonView.git " , from : " 1.7.0 " )
]IMPORTANTE!
Desde a versão 1.30.0,
SkeletonViewsuporta o XCFRameWorks ; portanto, se você deseja instalá -lo como um xcframework , use este repositório.
Apenas 3 etapas necessárias para usar SkeletonView :
1sent importar o SkeletonView no lugar apropriado.
import SkeletonView 2️⃣ Agora, defina quais visualizações serão skeletonables . Você consegue isso de duas maneiras:
Usando código:
avatarImageView . isSkeletonable = trueUsando ib/storyboards:

3️⃣ Depois de definir as visualizações, você pode mostrar o esqueleto . Para fazer isso, você tem 4 opções:
( 1 ) view . showSkeleton ( ) // Solid
( 2 ) view . showGradientSkeleton ( ) // Gradient
( 3 ) view . showAnimatedSkeleton ( ) // Solid animated
( 4 ) view . showAnimatedGradientSkeleton ( ) // Gradient animatedVisualização
| Sólido | Gradiente | Animado sólido | Gradiente animado |
![]() | ![]() | ![]() | ![]() |
IMPORTANTE!
SkeletonViewé recursivo; portanto, se você deseja mostrar o esqueleto em todas as visualizações esqueléticas, você só precisa chamar o método Show na visualização principal do contêiner. Por exemplo, comUIViewControllers.
SkeletonView é compatível com UITableView e UICollectionView .
UabableView
Se você deseja mostrar o esqueleto em um UITableView , precisará se conformar para o SkeletonTableViewDataSource Protocol.
public protocol SkeletonTableViewDataSource : UITableViewDataSource {
func numSections ( in collectionSkeletonView : UITableView ) -> Int // Default: 1
func collectionSkeletonView ( _ skeletonView : UITableView , numberOfRowsInSection section : Int ) -> Int
func collectionSkeletonView ( _ skeletonView : UITableView , cellIdentifierForRowAt indexPath : IndexPath ) -> ReusableCellIdentifier
func collectionSkeletonView ( _ skeletonView : UITableView , skeletonCellForRowAt indexPath : IndexPath ) -> UITableViewCell ? // Default: nil
func collectionSkeletonView ( _ skeletonView : UITableView , prepareCellForSkeleton cell : UITableViewCell , at indexPath : IndexPath )
} Como você pode ver, esse protocolo herda do UITableViewDataSource , para que você possa substituir esse protocolo pelo protocolo do esqueleto.
Este protocolo possui uma implementação padrão para alguns métodos. Por exemplo, o número de linhas para cada seção é calculado em tempo de execução:
func collectionSkeletonView ( _ skeletonView : UITableView , numberOfRowsInSection section : Int ) -> Int
// Default:
// It calculates how many cells need to populate whole tableviewIMPORTANTE!
Se você retornar
UITableView.automaticNumberOfSkeletonRows.
Existe apenas um método que você precisa implementar para informar o Skeleton a saber o identificador da célula. Este método não possui implementação padrão:
func collectionSkeletonView ( _ skeletonView : UITableView , cellIdentifierForRowAt indexPath : IndexPath ) -> ReusableCellIdentifier {
return " CellIdentifier "
}Por padrão, a biblioteca dequei as células de cada IndexPath, mas você também pode fazer isso se quiser fazer algumas alterações antes que o esqueleto apareça:
func collectionSkeletonView ( _ skeletonView : UITableView , skeletonCellForRowAt indexPath : IndexPath ) -> UITableViewCell ? {
let cell = skeletonView . dequeueReusableCell ( withIdentifier : " CellIdentifier " , for : indexPath ) as? Cell
cell ? . textField . isHidden = indexPath . row == 0
return cell
}Se você preferir deixar a parte deque na biblioteca, pode configurar a célula usando este método:
func collectionSkeletonView ( _ skeletonView : UITableView , prepareCellForSkeleton cell : UITableViewCell , at indexPath : IndexPath ) {
let cell = cell as? Cell
cell ? . textField . isHidden = indexPath . row == 0
} Além disso, você pode esquelar os cabeçalhos e os rodapés. Você precisa se conformar para o SkeletonTableViewDelegate Protocol.
public protocol SkeletonTableViewDelegate : UITableViewDelegate {
func collectionSkeletonView ( _ skeletonView : UITableView , identifierForHeaderInSection section : Int ) -> ReusableHeaderFooterIdentifier ? // default: nil
func collectionSkeletonView ( _ skeletonView : UITableView , identifierForFooterInSection section : Int ) -> ReusableHeaderFooterIdentifier ? // default: nil
}IMPORTANTE!
1sent, se você estiver usando células redimensíveis (
tableView.rowHeight = UITableViewAutomaticDimension), é obrigatório definir oestimatedRowHeight.2️⃣ Quando você adiciona elementos em um
UITableViewCell, adicione -o aocontentViewe não à célula diretamente.self . contentView . addSubview ( titleLabel ) ✅ self . addSubview ( titleLabel )
UicollectionView
Para UICollectionView , você precisa se conformar para o SkeletonCollectionViewDataSource Protocol.
public protocol SkeletonCollectionViewDataSource : UICollectionViewDataSource {
func numSections ( in collectionSkeletonView : UICollectionView ) -> Int // default: 1
func collectionSkeletonView ( _ skeletonView : UICollectionView , numberOfItemsInSection section : Int ) -> Int
func collectionSkeletonView ( _ skeletonView : UICollectionView , cellIdentifierForItemAt indexPath : IndexPath ) -> ReusableCellIdentifier
func collectionSkeletonView ( _ skeletonView : UICollectionView , supplementaryViewIdentifierOfKind : String , at indexPath : IndexPath ) -> ReusableCellIdentifier ? // default: nil
func collectionSkeletonView ( _ skeletonView : UICollectionView , skeletonCellForItemAt indexPath : IndexPath ) -> UICollectionViewCell ? // default: nil
func collectionSkeletonView ( _ skeletonView : UICollectionView , prepareCellForSkeleton cell : UICollectionViewCell , at indexPath : IndexPath )
func collectionSkeletonView ( _ skeletonView : UICollectionView , prepareViewForSkeleton view : UICollectionReusableView , at indexPath : IndexPath )
} O restante do processo é o mesmo que UITableView

Ao usar elementos com texto, SkeletonView desenha linhas para simular o texto.
Você pode definir algumas propriedades para elementos multilines.
| Propriedade | Tipo | Padrão | Visualização |
|---|---|---|---|
| LastLineFillPercent | CGFloat | 70 | ![]() |
| LinesCornerradius | Int | 0 | ![]() |
| SkeletonLinesPacing | CGFloat | 10 | ![]() |
| SkeletonPaddingInsets | UIEdgeInsets | .zero | ![]() |
| SkeleTontextLineHeight | SkeletonTextLineHeight | .fixed(15) | ![]() |
| skeleletToxtNumberOflines | SkeletonTextNumberOfLines | .inherited | ![]() |
Para modificar a porcentagem ou raio usando código , defina as propriedades:
descriptionTextView . lastLineFillPercent = 50
descriptionTextView . linesCornerRadius = 5Ou, se você preferir usar ib/storyboard :

Como definir o número de linhas?
Por padrão, o número de linhas é o mesmo que o valor da propriedade numberOfLines . E, se estiver definido como zero , calculará quantas linhas serão necessárias para preencher o esqueleto inteiro e desenhá -lo.
No entanto, se você deseja definir um número específico de linhas de esqueleto, poderá fazê -lo definindo a propriedade skeletonTextNumberOfLines . Esta propriedade possui dois valores possíveis, inherited que retorna o valor numberOfLines e custom(Int) que retorna o número específico de linhas especificadas como o valor associado.
Por exemplo:
label . skeletonTextNumberOfLines = 3 // .custom(3)
️ Descontinuado!useFontLineHeight foi descontinuado. Você pode usar o SkeleleTontextLineHeight :
descriptionTextView . skeletonTextLineHeight = . relativeToFont
IMPORTANTE!
Observe que, para visualizações sem várias linhas, a linha única será considerada a última linha.
Os esqueletos têm uma aparência padrão. Portanto, quando você não especifica as propriedades de cor, gradiente ou multilines, SkeletonView usa os valores padrão.
Valores padrão:
UIColor.skeletonDefault (o mesmo que .clouds , mas adaptável ao modo escuro)SkeletonGradient(baseColor: .skeletonDefault)CGFloatCGFloatIntIntCGFloat (Ibinspectable) (faça sua vista para o esqueleto com canto) Para obter esses valores padrão, você pode usar SkeletonAppearance.default . Usando esta propriedade, você também pode definir os valores:
SkeletonAppearance . default . multilineHeight = 20
SkeletonAppearance . default . tintColor = . green
️ Descontinuado!useFontLineHeight foi descontinuado. Você pode usar o textLineHeight :
SkeletonAppearance . default . textLineHeight = . relativeToFont
Você pode decidir com qual cor o esqueleto é matizado. Você só precisa passar como um parâmetro a cor ou gradiente que deseja.
Usando cores sólidas
view . showSkeleton ( usingColor : UIColor . gray ) // Solid
// or
view . showSkeleton ( usingColor : UIColor ( red : 25.0 , green : 30.0 , blue : 255.0 , alpha : 1.0 ) )Usando gradientes
let gradient = SkeletonGradient ( baseColor : UIColor . midnightBlue )
view . showGradientSkeleton ( usingGradient : gradient ) // GradientAlém disso, o SkeletonView apresenta 20 cores planas ??
UIColor.turquoise, UIColor.greenSea, UIColor.sunFlower, UIColor.flatOrange ...

O SkeletonView possui duas animações embutidas, pulso para esqueletos sólidos e deslizamento para gradientes.
Além disso, se você quiser fazer sua própria animação de esqueletos, é muito fácil.
O Skeleton fornece a função showAnimatedSkeleton , que possui um fechamento SkeletonLayerAnimation , onde você pode definir sua animação personalizada.
public typealias SkeletonLayerAnimation = ( CALayer ) -> CAAnimationVocê pode chamar a função assim:
view . showAnimatedSkeleton { ( layer ) -> CAAnimation in
let animation = CAAnimation ( )
// Customize here your animation
return animation
} Está disponível SkeletonAnimationBuilder . É um construtor fazer SkeletonLayerAnimation .
Hoje, você pode criar animações deslizantes para gradientes, decidindo a direção e definindo a duração da animação (padrão = 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 é uma enumeração, com esses casos:
| Direção | Visualização |
|---|---|
| .leftright | ![]() |
| . direito | ![]() |
| .topbottom | ![]() |
| .BotTomtop | ![]() |
| .Topleftbottomright | ![]() |
| .BottomrightTopleft | ![]() |
TRUQUE!
Existe outra maneira de criar animações deslizantes, apenas usando este atalho:
let animation = GradientDirection . leftToRight . slidingAnimation ( )
O Skeletonview tem transições internas para mostrar ou ocultar os esqueletos de uma maneira mais suave ?
Para usar a transição, basta adicionar o parâmetro transition ao seu showSkeleton() ou função hideSkeleton() com o tempo de transição, como este:
view . showSkeleton ( transition : . crossDissolve ( 0.25 ) ) //Show skeleton cross dissolve transition with 0.25 seconds fade time
view . hideSkeleton ( transition : . crossDissolve ( 0.25 ) ) //Hide skeleton cross dissolve transition with 0.25 seconds fade time O valor padrão é crossDissolve(0.25)
Visualização
| Nenhum | Dissolver cruzado |
![]() | ![]() |
Hierarquia
Como SkeletonView é recursivo e queremos que o esqueleto seja muito eficiente, queremos parar de recursão o mais rápido possível. Por esse motivo, você deve definir a visualização do contêiner como Skeletonable , porque o Skeleton parará de procurar subviews skeletonable assim que uma visualização não for esqueleto, quebrando a recursão.
Porque uma imagem vale mais que mil palavras:
Neste exemplo, temos um UIViewController com uma ContainerView e UITableView . Quando a visualização estiver pronta, mostramos o esqueleto usando este método:
view.showSkeleton()
isSkeletonable= ☠️
| Configuração | Resultado |
|---|---|
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
Layout do esqueleto
Às vezes, o layout do esqueleto pode não se encaixar no seu layout, porque os limites da visualização dos pais foram alterados. Por exemplo, girando o dispositivo.
Você pode retransmitir as vistas do esqueleto como assim:
override func viewDidLayoutSubviews ( ) {
view . layoutSkeletonIfNeeded ( )
}IMPORTANTE!
Você não deve chamar esse método. Na versão 1.8.1, você não precisa chamar esse método, a biblioteca é automaticamente. Portanto, você pode usar esse método apenas nos casos quando precisar atualizar o layout do esqueleto manualmente.
Atualizar esqueleto
Você pode alterar a configuração do esqueleto a qualquer momento, como sua cor, animação etc. com os seguintes métodos:
( 1 ) view . updateSkeleton ( ) // Solid
( 2 ) view . updateGradientSkeleton ( ) // Gradient
( 3 ) view . updateAnimatedSkeleton ( ) // Solid animated
( 4 ) view . updateAnimatedGradientSkeleton ( ) // Gradient animatedEscondendo vistas quando a animação começa
Às vezes, você quer esconder alguma visão quando a animação começar, então há uma propriedade rápida que você pode usar para fazer isso acontecer:
view . isHiddenWhenSkeletonIsActive = true // This works only when isSkeletonable = trueNão modifique a interação do usuário quando o esqueleto estiver ativo
Por padrão, a interação do usuário está desativada para itens esqueletonizados, mas se você não deseja modificar o indicador de interação do usuário quando o Skeleton estiver ativo, poderá usar a propriedade isUserInteractionDisabledWhenSkeletonIsActive :
view . isUserInteractionDisabledWhenSkeletonIsActive = false // The view will be active when the skeleton will be active.Não use a altura da linha da fonte para as linhas de esqueleto em rótulos
Falso para desativar o esqueleto para ajustar automaticamente a altura da fonte para um UILabel ou UITextView . Por padrão, a altura das linhas do esqueleto é ajustada automaticamente à altura da fonte para refletir com mais precisão o texto no rótulo Rect em vez de usar a caixa delimitadora.
label . useFontLineHeight = falseAtraso no esqueleto de show
Você pode adiar a apresentação do esqueleto se as visualizações atualizarem rapidamente.
func showSkeleton ( usingColor : UIColor ,
animated : Bool ,
delay : TimeInterval ,
transition : SkeletonTransitionStyle ) func showGradientSkeleton ( usingGradient : SkeletonGradient ,
animated : Bool ,
delay : TimeInterval ,
transition : SkeletonTransitionStyle )Depurar
Para facilitar as tarefas de depuração quando algo não está funcionando bem. SkeletonView possui algumas novas ferramentas.
Primeiro, UIView disponível em uma propriedade com suas informações de esqueleto:
var sk . skeletonTreeDescription : String Além disso, você pode ativar o novo modo de depuração . Você basta adicionar a variável de ambiente SKELETON_DEBUG e ativá -lo.

Então, quando o esqueleto aparecer, você pode ver a hierarquia de visualizações no console Xcode.
{
"type" : "UIView", // UITableView, UILabel...
"isSkeletonable" : true,
"reference" : "0x000000014751ce30",
"children" : [
{
"type" : "UIView",
"isSkeletonable" : true,
"children" : [ ... ],
"reference" : "0x000000014751cfa0"
}
]
}
Versões OS e SDK suportadas
Este é um projeto de código aberto, portanto, fique à vontade para contribuir. Como?
Veja todos os colaboradores
Para mais informações, leia as diretrizes contribuintes.
Projetos de código aberto não podem viver muito sem a sua ajuda. Se você achar que o SkeletonView é útil, considere apoiar este projeto, tornando -se um patrocinador.
Torne -se um patrocinador através dos patrocinadores do GitHub ❤️
Juanpe Catalán
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.