Library

SkeletonUI

GREEN.1229 2022. 7. 25. 10:30

안녕하세요. 그린입니다🟢

이번 포스팅에서는 아주 예전부터 궁금했었는데 까먹고 있던 라이브러리 하나 보고 가려고합니다ㅎㅎ

바로 SkeletonUI 라는 외부 라이브러리입니다.

데이터를 받아올때 패칭이 완료되기전에 빈 공간으로 UI를 보여주는것보다 아래와 같은 이러한 데이터가 들어올 영역에 대해 뼈대를 잡는것이라 보면 될것 같아요.

이로 인해 조금 더 자연스러운 UI 경험을 시켜줄 수 있으며 빈 뷰로 나오면 버그라고 인식하기 쉬운 반면 이런것들을 적용시켜두면 로딩중이구나~ 라고 인식할 수 있어 사용자 경험에 더 좋은 영향을 끼칩니다🙌

 

그럼 이걸 쉽게 구현해놓은 SkeletonUI에 대해 알아보시죠!

아마 아주 간단할것 같아요 이번 포스팅은ㅎㅎ

 

SkeletonUI?

공식 리드미에서의 설명이 아주 간단히 되어 있어요.

SkeletonUI는 스켈레톤 방식의 로딩 애니메이션을 선언적인 구문을 통해 구현할 수 있게 해주었습니다.

로딩 화면 혹은 인디케이터를 사용하지 않고 스켈레톤 UI 방식을 이용해 동일한 효과를 나타낼 수 있으며 구현할 수 있습니다🙌

 

SkeletonUI 특징 및 장점

리드미에서 소개하는 특징이자 장점을 제가 추려서 소개해보겠습니다.

- 선언적인 SwiftUI와 잘 어울림

- 쉽고 간편한 설정

- 모든 뷰에 적용 가능하며 커스텀화도 가능

- 아이폰, 아이패드, 애플티비, 애플워치 등등 모든 플랫폼에 범용적임

- 가벼운 코드 기반

 

SkeletonUI 지원 버전

- macOS 10.15 이상

- Xcode 11.0 이상

- Swift 5.0 이상

- iOS 13.0 이상

- tvOS 13.0 이상

- watchOS 6.0 이상

SwiftUI를 사용하는 환경이라면 잘 어울리고 선언적 UI다 보니 쓰기 좋을것 같다고 생각했는데 전혀 문제가 되지 않겠네요!

 

SkeletonUI 설치

SPM과 코코아팟 두가지를 지원합니다.

아쉽지만 카르타고는 지원하지 않습니다🥲

SPM으로 설치 시 아래와 같이 Package 파일에 디펜던시를 추가해줍니다.

dependencies: [
.package(url: "https://github.com/CSolanaM/SkeletonUI.git", .branch("master"))
]

CocoaPods으로 설치 시는 팟 파일에 아래 팟을 추가해줍니다.

pod 'SkeletonUI

끝~~~~🥳

 

SkeletonUI 사용

이제 사용해볼까요?

아주 간단합니다.

예제는 리드미에 나온 예제를 가지고 테스트 해보겠습니다.

[기본 사용]

import SwiftUI
import SkeletonUI

struct SkeletonView: View {
  @State var colors = [String]()
  
  var body: some View {
    VStack {
      Spacer()
        .frame(height: 350)
      Text("Colors data download is completed")
        .skeleton(with: colors.isEmpty)
      Spacer()
        .frame(height: 350)
    }
    .onAppear {
      DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        self.colors = ["GREEN", "RED", "BLUE", "YELLOW", "BLACK"]
      }
    }
  }
}

위와 같이 적용시킬 뷰에 skeleton 메서드를 호출해줍니다.

저는 colors 프로퍼티가 비어있을때 스켈레톤 UI 뷰와 애니메이션이 노출되게 구현해줬어요.

이게 정해진 기본 사용 방식입니다.

당연히 색상 및 형태 지정을 해주려면 아래 커스텀 사용처럼 해줘야하겠죠.

우선 기본 사용을 통한 결과는 아래와 같습니다.

[커스텀 사용]

import SwiftUI
import SkeletonUI

struct CustomSkeletonView: View {
  @State var colors = [Color]()
  
  var body: some View {
    SkeletonList(with: colors, quantity: 10) { loading, color in
      Text(color?.name)
        .skeleton(with: loading)
        .shape(type: .rectangle)
        .appearance(type: .solid(color: .red, background: .blue))
        .multiline(lines: 3, scales: [1: 0.5])
        .animation(type: .pulse())
    }
    .onAppear {
      DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        self.colors = [
          Color(name: "GREEN"),
          Color(name: "RED"),
          Color(name: "BLUE"),
          Color(name: "BLACK")
        ]
      }
    }
  }
}

struct Color: Identifiable {
  let id = UUID()
  let name: String
}

이렇게 Color를 리스트로 뿌려주고 이에 대해 커스텀한 스켈레톤 뷰를 만들 수 있습니다.

SkeletonList 내부를 살펴보죠.

import SwiftUI

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public struct SkeletonList<Data, Content>: View where Data: RandomAccessCollection, Data.Element: Identifiable, Content: View {
    private let data: Data
    private let quantity: Int
    private let content: (Bool, Data.Element?) -> Content

    public init(with data: Data, quantity: Int = 1, @ViewBuilder content: @escaping (Bool, Data.Element?) -> Content) {
        self.data = data
        self.quantity = quantity
        self.content = content
    }

    public var body: some View {
        List(0 ..< (data.isEmpty ? quantity : data.count), id: \.self) { index in
            self.content(self.data.isEmpty, self.data.isEmpty ? nil : self.data.map { $0 }[index])
        }
    }
}

이렇게 내부 구현이 구성되어 있어요.

즉 content라는 클로저 안에 Bool 타입 즉 로딩이 되었는지를 판별할 수 있겠죠?

data는 정말 그대로 데이터로 들어올것들이에요.

그리고 quantity는 스켈레톤 뷰로 리스트를 띄워줄 셀의 갯수로 보면 됩니다.

데이터가 4개여도 저 값을 10개로 지정해두면 스켈레톤 뷰를 띄워줄때 10개의 셀로 보여지고 데이터를 다 리스폰 받으면 4개만 정상적으로 보여집니다.

그 외 형태, 컬러, 애니메이션 효과, 셀 내 라인 수 등 커스텀하게 제작할 수 있어요.

그럼 최종적으로 위의 구현은 아래와 같이 될 수 있습니다.

 

마무리

해보고 싶었던 아주 간단한 라이브러리였는데 이렇게 해보네요.

내부 구현도 까보니 어렵지 않고 직접 만들어 적용도 해볼 수 있겠더라구요..!?

조금 더 좋은 사용 경험을 위해 스켈레톤 구현은 필수적으로 생각이 드네요🤔

위 예제를 보고 커스텀하게 구현한 제 코드도 같이 공유드립니다🙌

https://github.com/GREENOVER/playground/tree/main/SkeletonTest

 

GitHub - GREENOVER/playground: 학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터

학습을 하며 간단한 예제들을 만들어 보는 작고 소중한 놀이터. Contribute to GREENOVER/playground development by creating an account on GitHub.

github.com

 

[참고자료]

https://github.com/CSolanaM/SkeletonUI

 

GitHub - CSolanaM/SkeletonUI: ☠️ Elegant skeleton loading animation in SwiftUI and Combine

☠️ Elegant skeleton loading animation in SwiftUI and Combine - GitHub - CSolanaM/SkeletonUI: ☠️ Elegant skeleton loading animation in SwiftUI and Combine

github.com

https://axelhodler.medium.com/creating-skeleton-loaders-in-swiftui-b8f005612814

 

Creating Skeleton Loaders in SwiftUI

In our apps we often populate lists with content that is fetched from elsewhere. Some server or service somewhere on the internet.

axelhodler.medium.com