UIView bottom border?

2019-01-03 08:03发布

To a UIScrollView *toScrollView (which is the width of the screen), I want to add a gray bottom border (exactly like that of the to-field of the compose view of the iPhone's native Messages app).

To achieve this, I followed Cocoa Touch: How To Change UIView's Border Color And Thickness? and just covered the top border with the custom UINavigationBar and made the toScrollView's x-coordinate -1 & width 322 so that the left & right borders are just off screen.

This looks fine, but it's sort of a hack, and I was wondering if there's a better way to do this.

- (void)viewDidLoad {
    [super viewDidLoad];

    // Add UINavigationBar *navigationBar at top.
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
                                             initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
                                             target:self action:@selector(cancelAction)];
    UINavigationBar *navigationBar = [[UINavigationBar alloc]
                                      initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)];
    navigationBar.items = [NSArray arrayWithObject:self.navigationItem];

    // Add UIScrollView *toScrollView below navigationBar.
    UIScrollView *toScrollView = [[UIScrollView alloc]
                                  initWithFrame:CGRectMake(-1.0f, 43.0f, 322.0f, 45.0f)];
    toScrollView.backgroundColor = [UIColor whiteColor];
    toScrollView.layer.borderColor = [UIColor colorWithWhite:0.8f alpha:1.0f].CGColor;
    toScrollView.layer.borderWidth = 1.0f;
    [self.view addSubview:toScrollView];
    [self.view addSubview:navigationBar]; // covers top of toScrollView
}

20条回答
戒情不戒烟
2楼-- · 2019-01-03 08:34

Swift 4 That's work fine by copy this UIView extension

extension UIView {

final func addBorder(edges: UIRectEdge, color: UIColor = UIColor.white, thickness: CGFloat = 1.0) -> [UIView] {

var borders = [UIView]()

func border() -> UIView {
  let border = UIView(frame: CGRect.zero)
  border.backgroundColor = color
  border.translatesAutoresizingMaskIntoConstraints = false
  return border
}

if edges.contains(.top) || edges.contains(.all) {
  let top = border()
  addSubview(top)
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[top(==thickness)]",
                                   options: [],
                                   metrics: ["thickness": thickness],
                                   views: ["top": top]))
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "H:|-(0)-[top]-(0)-|",
                                   options: [],
                                   metrics: nil,
                                   views: ["top": top]))
  borders.append(top)
}

if edges.contains(.left) || edges.contains(.all) {
  let left = border()
  addSubview(left)
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "H:|-(0)-[left(==thickness)]",
                                   options: [],
                                   metrics: ["thickness": thickness],
                                   views: ["left": left]))
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[left]-(0)-|",
                                   options: [],
                                   metrics: nil,
                                   views: ["left": left]))
  borders.append(left)
}

if edges.contains(.right) || edges.contains(.all) {
  let right = border()
  addSubview(right)
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "H:[right(==thickness)]-(0)-|",
                                   options: [],
                                   metrics: ["thickness": thickness],
                                   views: ["right": right]))
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "V:|-(0)-[right]-(0)-|",
                                   options: [],
                                   metrics: nil,
                                   views: ["right": right]))
  borders.append(right)
}

if edges.contains(.bottom) || edges.contains(.all) {
  let bottom = border()
  addSubview(bottom)
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "V:[bottom(==thickness)]-(0)-|",
                                   options: [],
                                   metrics: ["thickness": thickness],
                                   views: ["bottom": bottom]))
  addConstraints(
    NSLayoutConstraint.constraints(withVisualFormat: "H:|-(0)-[bottom]-(0)-|",
                                   options: [],
                                   metrics: nil,
                                   views: ["bottom": bottom]))
  borders.append(bottom)
}
  return borders
 }
}

In your ViewController, you can use it by:

_ = view.addBorder(edges: .bottom, color: UIColor.lightGray, thickness: 0.3)

You can change ".bottom" to top, left, or right, or array "[.bottom, .top]" that suit your work.

查看更多
男人必须洒脱
3楼-- · 2019-01-03 08:35

The most complete answer. https://github.com/oney/UIView-Border

let rectangle = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 60))
rectangle.backgroundColor = UIColor.grayColor()
view.addSubview(rectangle)
rectangle.borderTop = Border(size: 3, color: UIColor.orangeColor(), offset: UIEdgeInsets(top: 0, left: -10, bottom: 0, right: -5))
rectangle.borderBottom = Border(size: 6, color: UIColor.redColor(), offset: UIEdgeInsets(top: 0, left: 10, bottom: 10, right: 0))
rectangle.borderLeft = Border(size: 2, color: UIColor.blueColor(), offset: UIEdgeInsets(top: 10, left: -10, bottom: 0, right: 0))
rectangle.borderRight = Border(size: 2, color: UIColor.greenColor(), offset: UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 0))

enter image description here

查看更多
不美不萌又怎样
4楼-- · 2019-01-03 08:36

Swift 4

Based on https://stackoverflow.com/a/32513578/5391914

import UIKit
enum viewBorder: String {
    case Left = "borderLeft"
    case Right = "borderRight"
    case Top = "borderTop"
    case Bottom = "borderBottom"
}

extension UIView {

    func addBorder(vBorders: [viewBorder], color: UIColor, width: CGFloat) {
        vBorders.forEach { vBorder in
            let border = CALayer()
            border.backgroundColor = color.cgColor
            border.name = vBorder.rawValue
            switch vBorder {
            case .Left:
                border.frame = CGRect(x: 0, y: 0, width: width, height: self.frame.size.height)
            case .Right:
                border.frame = CGRect(x:self.frame.size.width - width, y: 0, width: width, height: self.frame.size.height)
            case .Top:
                border.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: width)
            case .Bottom:
                border.frame = CGRect(x: 0, y: self.frame.size.height - width , width: self.frame.size.width, height: width)
            }
            self.layer.addSublayer(border)
        }
    }
}
查看更多
看我几分像从前
5楼-- · 2019-01-03 08:37

Swift 4

Based on: https://stackoverflow.com/a/32821607/9980800

UIView+Border

extension UIView {

  enum ViewBorder: String {
      case left, right, top, bottom
  }

  func add(Border border: ViewBorder, withColor color: UIColor = UIColor.lightGray, andWidth width: CGFloat = 1.0) {

    let borderView = UIView()
    borderView.backgroundColor = color
    borderView.translatesAutoresizingMaskIntoConstraints = false
    self.addSubview(borderView)
    NSLayoutConstraint.activate(getConstrainsFor(forView: borderView, WithBorderType: border, andWidth: width))
  }

  private func getConstrainsFor(forView borderView: UIView, WithBorderType border: ViewBorder, andWidth width: CGFloat) -> [NSLayoutConstraint] {

    let height = borderView.heightAnchor.constraint(equalToConstant: width)
    let widthAnchor = borderView.widthAnchor.constraint(equalToConstant: width)
    let leading = borderView.leadingAnchor.constraint(equalTo: self.leadingAnchor)
    let trailing = borderView.trailingAnchor.constraint(equalTo: self.trailingAnchor)
    let top = borderView.topAnchor.constraint(equalTo: self.topAnchor)
    let bottom = borderView.bottomAnchor.constraint(equalTo: self.bottomAnchor)

    switch border {

    case .bottom:
        return [bottom, leading, trailing, height]

    case .top:
        return [top, leading, trailing, height]

    case .left:
        return [top, bottom, leading, widthAnchor]

    case .right:
        return [top, bottom, trailing, widthAnchor]
    }
}

}

Usage:-

class ViewController: UIViewController {

@IBOutlet weak var sampleView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    sampleView.add(Border: .bottom)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}
查看更多
老娘就宠你
6楼-- · 2019-01-03 08:38

Here is a more generalized Swift extension to create border for any UIView subclass:

import UIKit

extension UIView {      
  func addTopBorderWithColor(color: UIColor, width: CGFloat) {
    let border = CALayer()
    border.backgroundColor = color.CGColor
    border.frame = CGRectMake(0, 0, self.frame.size.width, width)
    self.layer.addSublayer(border)
  }

  func addRightBorderWithColor(color: UIColor, width: CGFloat) {
    let border = CALayer()
    border.backgroundColor = color.CGColor
    border.frame = CGRectMake(self.frame.size.width - width, 0, width, self.frame.size.height)
    self.layer.addSublayer(border)
  }

  func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
    let border = CALayer()
    border.backgroundColor = color.CGColor
    border.frame = CGRectMake(0, self.frame.size.height - width, self.frame.size.width, width)
    self.layer.addSublayer(border)
  }

  func addLeftBorderWithColor(color: UIColor, width: CGFloat) {
    let border = CALayer()
    border.backgroundColor = color.CGColor
    border.frame = CGRectMake(0, 0, width, self.frame.size.height)
    self.layer.addSublayer(border)
  }
}

Swift 3

extension UIView {
    func addTopBorderWithColor(color: UIColor, width: CGFloat) {
        let border = CALayer()
        border.backgroundColor = color.cgColor
        border.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: width)
        self.layer.addSublayer(border)
    }

    func addRightBorderWithColor(color: UIColor, width: CGFloat) {
        let border = CALayer()
        border.backgroundColor = color.cgColor
        border.frame = CGRect(x: self.frame.size.width - width, y: 0, width: width, height: self.frame.size.height)
        self.layer.addSublayer(border)
    }

    func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
        let border = CALayer()
        border.backgroundColor = color.cgColor
        border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: width)
        self.layer.addSublayer(border)
    }

    func addLeftBorderWithColor(color: UIColor, width: CGFloat) {
        let border = CALayer()
        border.backgroundColor = color.cgColor
        border.frame = CGRect(x: 0, y: 0, width: width, height: self.frame.size.height)
        self.layer.addSublayer(border)
    }
}
查看更多
可以哭但决不认输i
7楼-- · 2019-01-03 08:38

Swift 4

If you need a really adaptive solution (for all screen sizes), then this is it:

/**
* Extends UIView with shortcut methods
*
* @author Alexander Volkov
* @version 1.0
*/
extension UIView {

    /// Adds bottom border to the view with given side margins
    ///
    /// - Parameters:
    ///   - color: the border color
    ///   - margins: the left and right margin
    ///   - borderLineSize: the size of the border
    func addBottomBorder(color: UIColor = UIColor.red, margins: CGFloat = 0, borderLineSize: CGFloat = 1) {
        let border = UIView()
        border.backgroundColor = color
        border.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(border)
        border.addConstraint(NSLayoutConstraint(item: border,
                                                attribute: .height,
                                                relatedBy: .equal,
                                                toItem: nil,
                                                attribute: .height,
                                                multiplier: 1, constant: borderLineSize))
        self.addConstraint(NSLayoutConstraint(item: border,
                                              attribute: .bottom,
                                              relatedBy: .equal,
                                              toItem: self,
                                              attribute: .bottom,
                                              multiplier: 1, constant: 0))
        self.addConstraint(NSLayoutConstraint(item: border,
                                              attribute: .leading,
                                              relatedBy: .equal,
                                              toItem: self,
                                              attribute: .leading,
                                              multiplier: 1, constant: margins))
        self.addConstraint(NSLayoutConstraint(item: border,
                                              attribute: .trailing,
                                              relatedBy: .equal,
                                              toItem: self,
                                              attribute: .trailing,
                                              multiplier: 1, constant: margins))
    }
}
查看更多
登录 后发表回答