CALayer: add a border only at one side

前端 未结 7 2036
北荒
北荒 2020-11-28 02:56

I can add a border to a CALayer in this way:

[webView.layer setBorderColor: [[UIColor colorWithRed:0.6 green:0.7 blue:0.2 alpha:1] CGColor]];
[webView.layer          


        
相关标签:
7条回答
  • 2020-11-28 03:08

    My Swift Solution. It involves four different functions, all extensions to UIView. Each function adds a different border.

    extension UIView {
    @discardableResult func addRightBorder(color: UIColor, width: CGFloat) -> UIView {
        let layer = CALayer()
        layer.borderColor = color.cgColor
        layer.borderWidth = width
        layer.frame = CGRect(x: self.frame.size.width-width, y: 0, width: width, height: self.frame.size.height)
        self.layer.addSublayer(layer)
        return self
        }
    @discardableResult func addLeftBorder(color: UIColor, width: CGFloat) -> UIView {
        let layer = CALayer()
        layer.borderColor = color.cgColor
        layer.borderWidth = width
        layer.frame = CGRect(x: 0, y: 0, width: width, height: self.frame.size.height)
        self.layer.addSublayer(layer)
        return self
        }
    @discardableResult func addTopBorder(color: UIColor, width: CGFloat) -> UIView {
        let layer = CALayer()
        layer.borderColor = color.cgColor
        layer.borderWidth = width
        layer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: width)
        self.layer.addSublayer(layer)
        return self
        }
    @discardableResult func addBottomBorder(color: UIColor, width: CGFloat) -> UIView {
        let layer = CALayer()
        layer.borderColor = color.cgColor
        layer.borderWidth = width
        layer.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: width)
        self.layer.addSublayer(layer)
        return self
        }
    }
    
    0 讨论(0)
  • 2020-11-28 03:11

    The easiest way is to add a subLayer that will draw the selective borders, but there are some things to consider when choosing this solution, the biggest are making sure that the borders subLayer is always on top, and that the borders change when you change the frame of your layer.

    I implemented a drop in open source solution that takes care of those issues, and let you declare selective borders like this:

    myView.borderDirection = AUIFlexibleBordersDirectionRight | AUIFlexibleBordersDirectionTop;
    

    You can get the code, and read about it some more here

    0 讨论(0)
  • 2020-11-28 03:13

    There's another way of doing this. The CAShapeLayer has properties called "strokeStart" and "strokeEnd". Considering the stroking starts from 0 and ends at 1 when it reaches the origin back, thus completing the path, you can set values to start and end to draw the border on one side.

    The relative location at which to begin stroking the path. Animatable. The value of this property must be in the range 0.0 to 1.0. The default value of this property is 0.0. Combined with the strokeEnd property, this property defines the subregion of the path to stroke. The value in this property indicates the relative point along the path at which to begin stroking while the strokeEnd property defines the end point. A value of 0.0 represents the beginning of the path while a value of 1.0 represents the end of the path. Values in between are interpreted linearly along the path length.

    Example:

    let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.CGPath
    mask.strokeColor = UIColor.redColor().CGColor
    mask.strokeStart = 0.45
    mask.strokeEnd = 0.92
    self.layer.mask = mask
    
    0 讨论(0)
  • 2020-11-28 03:14

    The following works with Swift 4.2 for applying a border along an existing UIView.

    extension UIView {
        enum Side {
            case top
            case bottom
            case left
            case right
        }
    
        func addBorder(to side: Side, color: UIColor, borderWidth: CGFloat) {
            let subLayer = CALayer()
            subLayer.borderColor = color.cgColor
            subLayer.borderWidth = borderWidth
            let origin = findOrigin(side: side, borderWidth: borderWidth)
            let size = findSize(side: side, borderWidth: borderWidth)
            subLayer.frame = CGRect(origin: origin, size: size)
            layer.addSublayer(subLayer)
        }
    
        private func findOrigin(side: Side, borderWidth: CGFloat) -> CGPoint {
            switch side {
            case .right:
                return CGPoint(x: frame.maxX - borderWidth, y: 0)
            case .bottom:
                return CGPoint(x: 0, y: frame.maxY - borderWidth)
            default:
                return .zero
            }
        }
    
        private func findSize(side: Side, borderWidth: CGFloat) -> CGSize {
            switch side {
            case .left, .right:
                return CGSize(width: borderWidth, height: frame.size.height)
            case .top, .bottom:
                return CGSize(width: frame.size.width, height: borderWidth)
            }
        }
    }
    

    And you can call it with this:

    myView.addBorder(to: .left, color: .black, borderWidth: 2.0)
    

    What is going on:

    • The user provides a Side as defined in the enum, along with a color and borderWidth
    • A new subLayer is created and given a borderColor and borderWidth
    • The origin is calculated, as determined by the side
    • The size is calculated, also as determined by the side
    • Finally, the layer is given a frame and then added as a sublayer
    0 讨论(0)
  • 2020-11-28 03:17

    I made a right border using this:

    leftScrollView.clipsToBounds = YES;
    
    CALayer *rightBorder = [CALayer layer];
    rightBorder.borderColor = [UIColor darkGrayColor].CGColor;
    rightBorder.borderWidth = 1;
    rightBorder.frame = CGRectMake(-1, -1, CGRectGetWidth(leftScrollView.frame), CGRectGetHeight(leftScrollView.frame)+2);
    
    [leftScrollView.layer addSublayer:rightBorder];
    
    0 讨论(0)
  • 2020-11-28 03:30

    Here's the swift equivalent

    leftScrollView.clipsToBounds = true
    let rightBorder: CALayer = CALayer()
    rightBorder.borderColor = UIColor.darkGrayColor().CGColor
    rightBorder.borderWidth = 1
    rightBorder.frame = CGRectMake(-1, -1, CGRectGetWidth(leftScrollView.frame), CGRectGetHeight(leftScrollView.frame)+2)
    leftScrollView.layer.addSublayer(rightBorder)
    
    0 讨论(0)
提交回复
热议问题