You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SwiftUI制作特定圆角样式的UI卡片组件?

SwiftUI 实现特定圆角UI卡片组件的标准方案

我在Pinterest上看到很多酷炫的UI卡片设计,想学习如何用SwiftUI制作这类卡片组件。尝试编写代码实现特定圆角的图片裁剪,但效果未达预期,附上现有代码,寻求标准实现方法。

现有尝试代码

import SwiftUI
struct RoundedCorners: Shape {
    var radius: CGFloat = 25.0
    var corners: UIRectCorner = .allCorners
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(
            roundedRect: rect,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius)
        )
        return Path(path.cgPath)
    }
}
struct ContentView: View {
    var body: some View {
        Image("images")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 200, height: 200)
            .clipShape(RoundedCorners(radius: 50, corners: [.topLeft, .bottomRight]))
            .shadow(radius: 5)
            .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

方案1:用SwiftUI内置Modifier(推荐,iOS 15+)

从iOS 15开始,SwiftUI原生支持指定圆角的角落,无需自定义Shape,代码更简洁易维护:

import SwiftUI

struct ContentView: View {
    var body: some View {
        // 完整Pinterest风格卡片示例,包含图片+文字内容
        VStack(alignment: .leading, spacing: 12) {
            // 带特定圆角的图片区域
            Image("images")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(height: 180)
                // 直接指定要圆角的角落:左上+右下
                .cornerRadius(24, corners: [.topLeft, .bottomRight])
            
            // 卡片文字内容区
            VStack(alignment: .leading, spacing: 6) {
                Text("潮流穿搭指南")
                    .font(.headline)
                    .fontWeight(.semibold)
                Text("分享最新街头穿搭技巧,打造专属风格")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }
            .padding(.horizontal, 16)
            .padding(.bottom, 16)
        }
        .frame(width: 280)
        .background(Color.white)
        // 给整个卡片统一加相同圆角,避免内容溢出
        .cornerRadius(24, corners: [.topLeft, .bottomRight])
        // 模拟Pinterest的柔和阴影
        .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
        .padding()
        .background(Color(.systemGray6))
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

方案2:兼容旧版本的自定义Shape优化

如果需要支持iOS 14及以下,可以优化你的自定义Shape,添加动画支持并封装成Modifier方便复用:

import SwiftUI

struct RoundedCorners: Shape {
    var radius: CGFloat
    var corners: UIRectCorner
    
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect,
                                byRoundingCorners: corners,
                                cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
    
    // 添加动画支持,让圆角变化更流畅
    var animatableData: AnimatablePair<CGFloat, UIRectCorner.AnimatableData> {
        get { AnimatablePair(radius, corners.animatableData) }
        set {
            radius = newValue.first
            corners.animatableData = newValue.second
        }
    }
}

// 封装成View扩展,调用更简洁
extension View {
    func roundedCorners(radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape(RoundedCorners(radius: radius, corners: corners))
    }
}

struct ContentView: View {
    var body: some View {
        Image("images")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 200, height: 200)
            .roundedCorners(radius: 50, corners: [.topLeft, .bottomRight])
            // 调整阴影参数让效果更自然
            .shadow(color: .black.opacity(0.15), radius: 5, x: 0, y: 2)
            .padding()
    }
}

核心注意事项

  • 使用.aspectRatio(contentMode: .fill)时,必须配合.frame固定尺寸,防止图片拉伸变形
  • 完整卡片建议用容器(如VStack)包裹所有元素,统一设置圆角和阴影,避免内容超出裁剪范围
  • 阴影可以通过调整opacity、radius和偏移量,模拟Pinterest卡片的柔和悬浮效果

内容的提问来源于stack exchange,提问作者BlurryFace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:58:18