如何制作此类卡片组件

问题描述 投票:0回答:1

我只是想知道制作 Ui 设计卡片的组件是什么。因为我在 pinterest 上看到了很多很酷的卡片设计,我想知道如何制作它。比如用 SwiftUI 进行这样的设计需要哪些组件

card UI

我已经试过了!我进一步扩展图像是这样的

my image


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) // Set your desired image size
            .clipShape(RoundedCorners(radius: 50, corners: [.topLeft, .bottomRight]))
            .shadow(radius: 5)
            .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我已经尝试过这个但不能。如果有人知道如何用标准来制作这个。

ios swift swiftui
1个回答
0
投票

可以通过创建路径并向其添加圆弧来构建基本形状。

  • 一种方法是创建自定义

    Shape
    ,就像您最初所做的那样。然而,这样做的话,很难在左上角保留正确的空间来显示标签,当然除非标签的大小是固定的。

  • 如果您想显示一个可以包含不同大小的文本并适应动态字体大小的标签,那么另一种方法是使用

    Canvas
    。然后,您可以将标签作为“符号”传入画布以供使用。

  • A

    Canvas
    接收
    GraphicsContext
    作为参数,这可以让您测量图像和其他符号的大小。因此,这使得构建一条完全适合标签尺寸的路径成为可能。

  • 绘制曲线的一个简单方法是使用 addArc(tangent1End:tangent2End:radius:transform:)。在这里,您只需传入在绘制带有方角而不是圆角的形状时将使用的点。

我发现无法将点击手势附加到传递到

Canvas
的符号上。因此,对于右下角的圆形按钮,我建议将尺寸传递到画布,以便可以保留正确的空间量。然后将按钮显示为具有对齐方式的覆盖层
.bottomTrailing

这里有一个示例来展示它的工作方式:

struct CardWithInsetCorners: View {
    let label: String
    let image: Image
    let roundButtonDiameter: CGFloat
    let roundedCornerRadius: CGFloat = 10
    let gapToCornerItems: CGFloat = 3

    var body: some View {
        Canvas { ctx, size in
            if let label = ctx.resolveSymbol(id: "label") {

                // Draw the label in the top-left corner
                let wLabel = label.size.width + gapToCornerItems
                let hLabel = label.size.height + gapToCornerItems
                ctx.draw(
                    label,
                    in: CGRect(origin: .zero, size: label.size)
                )
                // Build a path with rounded corners
                let wButton = roundButtonDiameter + gapToCornerItems
                let hButton = roundButtonDiameter + gapToCornerItems
                let path = Path { path in

                    // Begin half-way down the left side
                    path.move(to: CGPoint(x: 0, y: size.height / 2))

                    // Rounded-corner bottom-left of label
                    path.addArc(
                        tangent1End: CGPoint(x: 0, y: hLabel),
                        tangent2End: CGPoint(x: wLabel, y: hLabel),
                        radius: roundedCornerRadius
                    )
                    // Rounded-corner bottom-right of label
                    path.addArc(
                        tangent1End: CGPoint(x: wLabel, y: hLabel),
                        tangent2End: CGPoint(x: wLabel, y: 0),
                        radius: hLabel / 2
                    )
                    // Rounded-corner top-right of label
                    path.addArc(
                        tangent1End: CGPoint(x: wLabel, y: 0),
                        tangent2End: CGPoint(x: size.width, y: 0),
                        radius: roundedCornerRadius
                    )
                    // Rounded-corner top-right
                    path.addArc(
                        tangent1End: CGPoint(x: size.width, y: 0),
                        tangent2End: CGPoint(x: size.width, y: size.height - hButton),
                        radius: roundedCornerRadius
                    )
                    // Rounded-corner top-right of rounded button
                    path.addArc(
                        tangent1End: CGPoint(x: size.width, y: size.height - hButton),
                        tangent2End: CGPoint(x: size.width - wButton, y: size.height - hButton),
                        radius: roundedCornerRadius
                    )
                    // Rounded-corner top-left of rounded button
                    path.addArc(
                        tangent1End: CGPoint(x: size.width - wButton, y: size.height - hButton),
                        tangent2End: CGPoint(x: size.width - wButton, y: size.height),
                        radius: wButton / 2
                    )
                    // Rounded-corner bottom-left of rounded button
                    path.addArc(
                        tangent1End: CGPoint(x: size.width - wButton, y: size.height),
                        tangent2End: CGPoint(x: 0, y: size.height),
                        radius: roundedCornerRadius
                    )
                    // Rounded-corner bottom-left
                    path.addArc(
                        tangent1End: CGPoint(x: 0, y: size.height),
                        tangent2End: CGPoint(x: 0, y: size.height / 2),
                        radius: roundedCornerRadius
                    )
                    path.closeSubpath()
                }
                // Use the path as clip shape for subsequent drawing operations
                ctx.clip(to: path)

                // Compute the size for the image when scaled to fill
                let resolvedImage = ctx.resolve(image)
                let wImage = resolvedImage.size.width
                let hImage = resolvedImage.size.height
                let scalingFactor = max(size.width / wImage, size.height / hImage)
                let w = wImage * scalingFactor
                let h = hImage * scalingFactor
                let xImage = (size.width - w) / 2
                let yImage = (size.height - h) / 2

                // Show the image
                ctx.draw(
                    resolvedImage,
                    in: CGRect(origin: CGPoint(x: xImage, y: yImage), size: CGSize(width: w, height: h))
                )
            }
        } symbols: {
            Text(label)
                .font(.subheadline)
                .padding(.horizontal, 20)
                .padding(.vertical, 6)
                .background {
                    Capsule()
                        .fill(Color(.systemGray5))
                }
                .tag("label")
        }
    }
}

struct ContentView: View {
    let roundButtonDiameter: CGFloat = 44

    var body: some View {
        CardWithInsetCorners(
            label: "Music",
            image: Image(.image3),
            roundButtonDiameter: roundButtonDiameter
        )
        .overlay(alignment: .bottomTrailing) {
            Image(systemName: "heart")
                .resizable()
                .scaledToFit()
                .padding(12)
                .frame(width: roundButtonDiameter, height: roundButtonDiameter)
                .background {
                    Circle()
                        .fill(Color(.systemGray5))
                }
                .onTapGesture {
                    print("+like")
                }
        }
        .frame(height: 350)
        .frame(maxHeight: .infinity, alignment: .top)
    }
}

Screenshot

© www.soinside.com 2019 - 2024. All rights reserved.