Created
January 30, 2023 05:15
-
-
Save snowzurfer/61d59730f31b86098c323f0b5a709872 to your computer and use it in GitHub Desktop.
SwiftUI animated Skeleton Image and demo usage with NukeUI Image.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// LazyImageWithLoadingStates.swift | |
// | |
// Copyright © 2023 Alberto Taiuti. All rights reserved. | |
// | |
import os | |
import NukeUI | |
import SwiftUI | |
import SFSafeSymbols | |
struct LazyImageWithLoadingStates: View { | |
let imageRequest: ImageRequest | |
static private let log = Logger.makeLogger(type: LazyImageWithLoadingStates.self) | |
var body: some View { | |
LazyImage(request: imageRequest) { state in | |
if let image = state.image { | |
// Displays the loaded image. | |
image | |
} else if state.error != nil { | |
VStack { | |
SwiftUI.Image(systemSymbol: SFSymbol.exclamationmarkTriangleFill) | |
.font(.body) | |
Text("ERROR_RETRIEVING_IMAGE") | |
.font(.caption) | |
.multilineTextAlignment(.center) | |
.padding(.horizontal, 4) | |
} | |
.frame(maxWidth: .infinity, maxHeight: .infinity) | |
} else { | |
// Acts as a placeholder. | |
GraySkeletonImage() | |
} | |
} | |
.onFailure { error in | |
Self.log.error("Failed image download task, error: \(error)") | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SkeletonImage.swift | |
// | |
// Copyright © 2023 Alberto Taiuti. All rights reserved. | |
// | |
import SwiftUI | |
struct SkeletonImage: View { | |
let startColor: Color | |
let endColor: Color | |
let animationDuration: CGFloat | |
@State private var color = Color(.systemGray6) | |
var body: some View { | |
Rectangle() | |
.fill(color) | |
.onAppear { | |
color = startColor | |
withAnimation(.easeInOut(duration: animationDuration).repeatForever()) { | |
color = endColor | |
} | |
} | |
} | |
} | |
struct GraySkeletonImage: View { | |
var body: some View { | |
// Arrived at empirically | |
SkeletonImage(startColor: Color(.systemGray6), endColor: Color(.systemGray4), animationDuration: 0.9) | |
} | |
} | |
struct SkeletonImage_Previews: PreviewProvider { | |
static var previews: some View { | |
GraySkeletonImage() | |
.frame(width: 180, height: 300) | |
.cornerRadius(10) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment