SwiftUI - Add Border to One Edge of an Image

前端 未结 3 700
说谎
说谎 2021-02-04 09:07

It\'s a pretty straight-forward question - how does one apply a border effect to only the wanted edges of an Image with SwiftUI?

For example, I only want to apply a borde

相关标签:
3条回答
  • 2021-02-04 09:29

    If somebody ever needs to just add a quick 1 (or more) sided border to a view (e.g., the top edge, or any random combination of edges), I've found this works well and is tweakable:

    top edge:

    .overlay(Rectangle().frame(width: nil, height: 1, alignment: .top).foregroundColor(Color.gray), alignment: .top)
    

    leading edge:

    .overlay(Rectangle().frame(width: 1, height: nil, alignment: .leading).foregroundColor(Color.gray), alignment: .leading)
    

    etc.

    Just tweak the height, width, and edge to produce the combination of borders you want.

    0 讨论(0)
  • 2021-02-04 09:45

    Similar to @smakus, if you don't need to control color or thickness, you can just do this:

        .overlay(Divider(), alignment: .top)
        .overlay(Divider(), alignment: .bottom)
    
    0 讨论(0)
  • 2021-02-04 09:49

    Demo


    Implementation

    You can use this modifier on any View:

    .border(width: 5, edges: [.top, .leading], color: .yellow)
    

    With the help of this simple extension:

    extension View {
        func border(width: CGFloat, edges: [Edge], color: Color) -> some View {
            overlay(EdgeBorder(width: width, edges: edges).foregroundColor(color))
        }
    }
    

    And here is the magic struct behind this:

    struct EdgeBorder: Shape {
    
        var width: CGFloat
        var edges: [Edge]
    
        func path(in rect: CGRect) -> Path {
            var path = Path()
            for edge in edges {
                var x: CGFloat {
                    switch edge {
                    case .top, .bottom, .leading: return rect.minX
                    case .trailing: return rect.maxX - width
                    }
                }
    
                var y: CGFloat {
                    switch edge {
                    case .top, .leading, .trailing: return rect.minY
                    case .bottom: return rect.maxY - width
                    }
                }
    
                var w: CGFloat {
                    switch edge {
                    case .top, .bottom: return rect.width
                    case .leading, .trailing: return self.width
                    }
                }
    
                var h: CGFloat {
                    switch edge {
                    case .top, .bottom: return self.width
                    case .leading, .trailing: return rect.height
                    }
                }
                path.addPath(Path(CGRect(x: x, y: y, width: w, height: h)))
            }
            return path
        }
    }
    
    0 讨论(0)
提交回复
热议问题