带有圆角和边框的视图

问题描述 投票:0回答:5
VStack {
    Text("some text")
    Button("Ok") {}
        .foregroundColor(.cyan)
        .padding()
}
.padding()
.background(.red)
.border(.blue, width: 5)
.cornerRadius(20)

我希望整个视图具有带圆角的蓝色边框(而不是与圆角蓝色边框重叠的红色正方形。如何实现?我似乎已经尝试了排序修改器的所有变体。

swiftui border viewmodifier
5个回答
150
投票

无论您应用什么圆角半径,SwiftUI 边框都有直边(

.cornerRadius
只是将视图剪辑为圆形蒙版,并且不调整边框的外观)。

如果你想要圆角边框,你需要覆盖和

.stroke
一个圆角矩形:

VStack {
    Text("some text")
    Button("Ok") {}
        .foregroundColor(.cyan)
        .padding()
}
.padding()
.background(.red)
.cornerRadius(20) /// make the background rounded
.overlay( /// apply a rounded border
    RoundedRectangle(cornerRadius: 20)
        .stroke(.blue, lineWidth: 5)
)

结果:


24
投票

有时仅仅添加覆盖层可能会产生不令人满意的结果(当使用的视图设计为无限宽度/高度时就是这种情况)

for example

所以我建议在尝试添加圆形边框时使用插图

.overlay(
    RoundedRectangle(cornerRadius: 20)
        .inset(by: 5) // inset value should be same as lineWidth in .stroke
        .stroke(.blue, lineWidth: 5)
)

6
投票

添加其他答案,这是您的

SwiftUI
应用程序的简洁扩展:

fileprivate struct ModifierCornerRadiusWithBorder: ViewModifier {
    var radius: CGFloat
    var borderLineWidth: CGFloat = 1
    var borderColor: Color = .gray
    var antialiased: Bool = true
    
    func body(content: Content) -> some View {
        content
            .cornerRadius(self.radius, antialiased: self.antialiased)
            .overlay(
                RoundedRectangle(cornerRadius: self.radius)
                    .inset(by: self.borderLineWidth)
                    .strokeBorder(self.borderColor, lineWidth: self.borderLineWidth, antialiased: self.antialiased)
            )
    }
}

extension View {
    func cornerRadiusWithBorder(radius: CGFloat, borderLineWidth: CGFloat = 1, borderColor: Color = .gray, antialiased: Bool = true) -> some View {
        modifier(ModifierCornerRadiusWithBorder(radius: radius, borderLineWidth: borderLineWidth, borderColor: borderColor, antialiased: antialiased))
    }
}

然后你就可以做

VStack {
    Text("some text")
    Button("Ok") {}
        .foregroundColor(.cyan)
        .padding()
}
.padding()
.background(.red)
.cornerRadiusWithBorder(radius: 20, borderLineWidth: 5, borderColor: . blue)

为了实现这个目标


5
投票
struct RoundedCorner: Shape {
    var radius: CGFloat = .infinity
    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)
    }
}

extension View {
    func roundedCornerWithBorder(lineWidth: CGFloat, borderColor: Color, radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape(RoundedCorner(radius: radius, corners: corners) )
            .overlay(RoundedCorner(radius: radius, corners: corners)
                .stroke(borderColor, lineWidth: lineWidth))
    }
}

如何使用不同的示例。

示例:1 - 使用带边框的所有边角半径。

  var body: some View {
        Text("Some Text")
            .padding()
            .background(.red)
            .roundedCornerWithBorder(lineWidth: 2, borderColor: .blue, radius: 4, corners: [.allCorners])        
    }

示例:2 - 用于带边框的左上角和左下角半径。

var body: some View {
    Text("Some Text")
        .padding()
        .background(.red)
        .roundedCornerWithBorder(lineWidth: 2, borderColor: .blue, radius: 20, corners: [.topLeft, .bottomLeft])
}

示例:3 - 用于带边框的右上角和右下角半径。

var body: some View {
    Text("Some Text")
        .padding()
        .background(.red)
        .roundedCornerWithBorder(lineWidth: 2, borderColor: .blue, radius: 20, corners: [.topRight, .bottomRight])
}

示例:4 - 用于带边框的左上角和右下角半径。

var body: some View {
    Text("Some Text")
        .padding()
        .background(.red)
        .roundedCornerWithBorder(lineWidth: 2, borderColor: .blue, radius: 20, corners: [.topLeft, .bottomRight])
}


1
投票

使用“.行程”可能被认为是最佳实践方法。不过,如果您想尝试,以下方法也足够了:

RoundedRectangle(cornerRadius: 20)
    .foregroundColor(.blue)
    .frame(width: 100, height: 100)
    .overlay(
        RoundedRectangle(cornerRadius: 20)
            .foregroundColor(.red)
            .frame(width: 90, height: 90)
            .overlay(
                VStack {
                    Text("some text")
                    Button("Ok") {}
                }
            )
    )

你会得到同样的结果。

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