Search This Blog

Sunday, October 29, 2017

How to add a border just to the one side of a UIView

We need to add border to UIView. Let's create view and place it in the center of screen with NSLayoutConstraint
var containerView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()
    self.containerView = UIView()
    self.containerView.backgroundColor = UIColor.red
    self.view.addSubview(containerView)
    self.containerView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        self.containerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
        self.containerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
        self.containerView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.3),
        self.containerView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.3)
    ])
}


Border using SubView


In viewDidAppear method add top border to view using addSubView method.
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let topBorderView = UIView(frame: CGRect(x: 0, y: 0,
                                                 width: self.containerView.frame.size.width,
                                                 height: 10))
    topBorderView.backgroundColor = UIColor.black
    self.containerView.addSubview(topBorderView)
}
Great, top border is added. But is it adaptive, what happen when parent view frame is changed. Let's see.


When parent view frame changed top border is not changed it's size.



Border using CALayer


Let's do the same using CALayer. Create new layer and add it as sublayer to parent view.
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let topBorderLayer = CALayer()
    topBorderLayer.backgroundColor = UIColor.black.cgColor
    topBorderLayer.frame = CGRect(x: 0, y: 0,
                                      width: self.containerView.frame.size.width,
                                      height: 10)
    self.containerView.layer.addSublayer(topBorderLayer)
}


But it still not adaptive solution.


Adaptive Border


For making really adaptive border we need to use AutoLayout and NSLayoutConstraint. We create view for border, add it as subview and set constraints to it according the side of view where we need to add border.
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let topBorderView = UIView(frame: CGRect.zero)
    topBorderView.backgroundColor = UIColor.black
    self.containerView.addSubview(topBorderView)
    topBorderView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        topBorderView.topAnchor.constraint(equalTo: self.containerView.topAnchor),
        topBorderView.leadingAnchor.constraint(equalTo: self.containerView.leadingAnchor),
        topBorderView.trailingAnchor.constraint(equalTo: self.containerView.trailingAnchor),
        topBorderView.heightAnchor.constraint(equalToConstant: 10)
        ])
    }


Adaptive Border Extension


For making this feature available for all other views we can create Extension for UIVIew class.
extension UIView {
    func addTopBorder(color: UIColor, width: CGFloat) {
        let topBorderView = UIView(frame: CGRect.zero)
        topBorderView.backgroundColor = color
        self.addSubview(topBorderView)
        topBorderView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            topBorderView.topAnchor.constraint(equalTo: self.topAnchor),
            topBorderView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            topBorderView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            topBorderView.heightAnchor.constraint(equalToConstant: width)
        ])
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.containerView.addTopBorder(color: UIColor.blue, width: 15.0)
}



Adaptive Border For Any Side


We can go further and create extension's method for adding borders for any side of view (and for all sides). We can specify which sides of view we need to add borders. For each side we create view and provide for it special constraints.
extension UIView {
    
    func addBorders(edges: UIRectEdge = .all, color: UIColor = .black, width: CGFloat = 1.0) {
       
        func createBorder() -> UIView {
            let borderView = UIView(frame: CGRect.zero)
            borderView.translatesAutoresizingMaskIntoConstraints = false
            borderView.backgroundColor = color
            return borderView
        }

        if (edges.contains(.all) || edges.contains(.top)) {
            let topBorder = createBorder()
            self.addSubview(topBorder)
            NSLayoutConstraint.activate([
                topBorder.topAnchor.constraint(equalTo: self.topAnchor),
                topBorder.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                topBorder.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                topBorder.heightAnchor.constraint(equalToConstant: width)
            ])
        }
        if (edges.contains(.all) || edges.contains(.left)) {
            let leftBorder = createBorder()
            self.addSubview(leftBorder)
            NSLayoutConstraint.activate([
                leftBorder.topAnchor.constraint(equalTo: self.topAnchor),
                leftBorder.bottomAnchor.constraint(equalTo: self.bottomAnchor),
                leftBorder.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                leftBorder.widthAnchor.constraint(equalToConstant: width)
                ])
        }
        if (edges.contains(.all) || edges.contains(.right)) {
            let rightBorder = createBorder()
            self.addSubview(rightBorder)
            NSLayoutConstraint.activate([
                rightBorder.topAnchor.constraint(equalTo: self.topAnchor),
                rightBorder.bottomAnchor.constraint(equalTo: self.bottomAnchor),
                rightBorder.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                rightBorder.widthAnchor.constraint(equalToConstant: width)
                ])
        }
        if (edges.contains(.all) || edges.contains(.bottom)) {
            let bottomBorder = createBorder()
            self.addSubview(bottomBorder)
            NSLayoutConstraint.activate([
                bottomBorder.bottomAnchor.constraint(equalTo: self.bottomAnchor),
                bottomBorder.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                bottomBorder.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                bottomBorder.heightAnchor.constraint(equalToConstant: width)
            ])
        }
    }
}

Using our Extension for UIView let's add only right and left borders to view.
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.containerView.addBorders(edges: [.left, .right], width: 8)
}



Using our Extension for UIView let's add borders to view. Because all parameters are set by default, we can specify only border width.
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.containerView.addBorders(width: 8)
}


Source Code


You can find source code of this post on github GitHub Link

10 comments:

  1. This is great, thank you so much ...

    ReplyDelete
  2. Thank you. This one should come up in google search instead of other one.

    ReplyDelete
  3. Have been looking for this for 2 weeks now. Thanks man

    ReplyDelete
  4. How do we add an adaptive gradient shadow using this model cos I couldn't figure it out

    ReplyDelete
  5. Great post! Thank you so much. I really need these tips. The detailed explanation is really helpful. Seeing how you write was very inspiring.
    -Custom Website Design Company

    ReplyDelete
  6. Your article is one of its kind which explained every bit of Custom Build Website. looking for further valuable articles from you

    ReplyDelete
  7. This is an excellent article! Thank you a lot. I'm in desperate need of these suggestions. The in-depth explanation is quite beneficial. It was incredibly encouraging to see how you write. Best Custom Websites

    ReplyDelete
  8. Thank you Sir, you made it easy as pie. Now i am able to understand and have enough knowledge about this. It is only because of you.
    Custom Designed Websites

    ReplyDelete
  9. This is a great article! Thank you very much. I really need these suggestions. An in-depth explanation is of great benefit. Incredibly inspiring to see how you write. Custom Website

    ReplyDelete
  10. Amazing write-up! The blog was very informative. Keep it up!
    Software Testing Services

    ReplyDelete