闽公网安备 35020302035485号

4.将这个效果应用到占位符上
struct Shimmer: ViewModifier {
@Stateprivatevar isInitialState = true
func body(content: Content) -> some View {
content
.mask(
LinearGradient(
gradient: Gradient(colors: [
.black.opacity(0.4),
.black,
.black.opacity(0.4)
]),
startPoint: isInitialState ?
UnitPoint(x: -0.3, y: -0.3) :
UnitPoint(x: 1, y: 1),
endPoint: isInitialState ?
UnitPoint(x: 0, y: 0) :
UnitPoint(x: 1.3, y: 1.3)
)
)
.animation(
.linear(duration: 1.5)
.delay(0.25)
.repeatForever(autoreverses: false),
value: isInitialState
)
.onAppear {
isInitialState = false
}
}
}
创建一个简单的加载视图struct ContentView: View {
@Stateprivatevar isLoading = true
var body: some View {
VStack(spacing: 20) {
if isLoading {
// 加载状态
VStack(spacing: 15) {
Rectangle()
.fill(Color.gray.opacity(0.3))
.frame(height: 200)
.cornerRadius(10)
HStack {
Circle()
.fill(Color.gray.opacity(0.3))
.frame(width: 60, height: 60)
VStack(alignment: .leading, spacing: 8) {
Rectangle()
.fill(Color.gray.opacity(0.3))
.frame(height: 16)
.cornerRadius(8)
Rectangle()
.fill(Color.gray.opacity(0.3))
.frame(width: 120, height: 16)
.cornerRadius(8)
}
// 堆代码 duidaima.com
Spacer()
}
}
.modifier(Shimmer())
} else {
// 实际内容
VStack(spacing: 15) {
Image("placeholder")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 200)
.cornerRadius(10)
HStack {
Circle()
.fill(Color.blue)
.frame(width: 60, height: 60)
VStack(alignment: .leading, spacing: 8) {
Text("美丽的风景")
.font(.headline)
Text("瑞士 · 阿尔卑斯山")
.font(.subheadline)
.foregroundColor(.secondary)
}
Spacer()
}
}
}
Button(isLoading ? "加载中..." : "重新加载") {
withAnimation {
isLoading.toggle()
}
}
.disabled(isLoading)
}
.padding()
.onAppear {
// 模拟加载时间
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation {
isLoading = false
}
}
}
}
}
看看效果(其实是有动画的,只是我截图截断了):
struct ShimmerView: View {
@Stateprivatevar startPoint = UnitPoint(x: -1.8, y: -1.2)
@Stateprivatevar endPoint = UnitPoint(x: 0, y: -0.2)
privatelet gradientColors = [
Color.gray.opacity(0.2),
Color.white.opacity(0.2),
Color.gray.opacity(0.2)
]
var body: some View {
LinearGradient(
colors: gradientColors,
startPoint: startPoint,
endPoint: endPoint
)
.onAppear {
withAnimation(
.easeInOut(duration: 1)
.repeatForever(autoreverses: false)
) {
startPoint = UnitPoint(x: 1, y: 1)
endPoint = UnitPoint(x: 2.2, y: 2.2)
}
}
}
}
实际应用场景4.分页加载 - 在加载更多内容时显示
4.无障碍支持 - 记得为使用辅助功能的用户提供替代方案