Swift Add Line Above to Control

Swift add line above to control

It is simple to add a subview to act as a line. For example:

Swift 4

var lineView = UIView(frame: CGRect(x: 0, y: 100, width: 320, height: 1.0))
lineView.layer.borderWidth = 1.0
lineView.layer.borderColor = UIColor.black.cgColor
self.view.addSubview(lineView)

Objective C

UIView * lineview = [[UIView alloc] initWithFrame:CGRectMake(0, 100,320,1)];
lineview.layer.borderColor = [UIColor blackColor].CGColor;
lineview.layer.borderWidth = 1.0;
[self.view addSubview:lineview];

Or you can refer to this link to add CALayer or draw a view

how do you draw a line programmatically from a view controller?

How to draw a line in the simplest way in swift

Try looking into UIBezierPath, it will help you a lot for drawing lines. Here is documentation. Here is an example:

override func drawRect(rect: CGRect) {
let aPath = UIBezierPath()

aPath.move(to: CGPoint(x:<#start x#>, y:<#start y#>))
aPath.addLine(to: CGPoint(x: <#end x#>, y: <#end y#>))

// Keep using the method addLine until you get to the one where about to close the path
aPath.close()

// If you want to stroke it with a red color
UIColor.red.set()
aPath.lineWidth = <#line width#>
aPath.stroke()
}

Make sure you put this code in the drawRect, like in the example above.

If you need to update the drawing just call setNeedsDisplay() to update.

How do you add multi-line text to a UIButton?

For iOS 6 and above, use the following to allow multiple lines:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

For iOS 5 and below use the following to allow multiple lines:

button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

2017, for iOS9 forward,

generally, just do these two things:

  1. choose "Attributed Text"
  2. on the "Line Break" popup select "Word Wrap"

How to add line break for UILabel?

Use \n as you are using in your string.

Set numberOfLines to 0 to allow for any number of lines.

label.numberOfLines = 0;

Update the label frame to match the size of the text using sizeWithFont:. If you don't do this your text will be vertically centered or cut off.

UILabel *label; // set frame to largest size you want
...
CGSize labelSize = [label.text sizeWithFont:label.font
constrainedToSize:label.frame.size
lineBreakMode:label.lineBreakMode];
label.frame = CGRectMake(
label.frame.origin.x, label.frame.origin.y,
label.frame.size.width, labelSize.height);

Update : Replacement for deprecated

sizeWithFont:constrainedToSize:lineBreakMode:

Reference, Replacement for deprecated sizeWithFont: in iOS 7?

CGSize labelSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];

label.frame = CGRectMake(
label.frame.origin.x, label.frame.origin.y,
label.frame.size.width, labelSize.height);

How do you draw a line programmatically from a view controller?

There are two common techniques.

  1. Using CAShapeLayer:

    • Create a UIBezierPath (replace the coordinates with whatever you want):

      UIBezierPath *path = [UIBezierPath bezierPath];
      [path moveToPoint:CGPointMake(10.0, 10.0)];
      [path addLineToPoint:CGPointMake(100.0, 100.0)];
    • Create a CAShapeLayer that uses that UIBezierPath:

      CAShapeLayer *shapeLayer = [CAShapeLayer layer];
      shapeLayer.path = [path CGPath];
      shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
      shapeLayer.lineWidth = 3.0;
      shapeLayer.fillColor = [[UIColor clearColor] CGColor];
    • Add that CAShapeLayer to your view's layer:

      [self.view.layer addSublayer:shapeLayer];

    In previous versions of Xcode, you had to manually add QuartzCore.framework to your project's "Link Binary with Libraries" and import the <QuartzCore/QuartzCore.h> header in your .m file, but that's not necessary anymore (if you have the "Enable Modules" and "Link Frameworks Automatically" build settings turned on).

  2. The other approach is to subclass UIView and then use CoreGraphics calls in the drawRect method:

    • Create a UIView subclass and define a drawRect that draws your line.

      You can do this with Core Graphics:

      - (void)drawRect:(CGRect)rect {
      CGContextRef context = UIGraphicsGetCurrentContext();

      CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
      CGContextSetLineWidth(context, 3.0);
      CGContextMoveToPoint(context, 10.0, 10.0);
      CGContextAddLineToPoint(context, 100.0, 100.0);
      CGContextDrawPath(context, kCGPathStroke);
      }

      Or using UIKit:

      - (void)drawRect:(CGRect)rect {
      UIBezierPath *path = [UIBezierPath bezierPath];
      [path moveToPoint:CGPointMake(10.0, 10.0)];
      [path addLineToPoint:CGPointMake(100.0, 100.0)];
      path.lineWidth = 3;
      [[UIColor blueColor] setStroke];
      [path stroke];
      }
    • Then you can either use this view class as the base class for your NIB/storyboard or view, or you can have your view controller programmatically add it as a subview:

      PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
      pathView.backgroundColor = [UIColor clearColor];

      [self.view addSubview: pathView];

The Swift renditions of the two above approaches are as follows:

  1. CAShapeLayer:

    // create path

    let path = UIBezierPath()
    path.move(to: CGPoint(x: 10, y: 10))
    path.addLine(to: CGPoint(x: 100, y: 100))

    // Create a `CAShapeLayer` that uses that `UIBezierPath`:

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = path.cgPath
    shapeLayer.strokeColor = UIColor.blue.cgColor
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineWidth = 3

    // Add that `CAShapeLayer` to your view's layer:

    view.layer.addSublayer(shapeLayer)
  2. UIView subclass:

    class PathView: UIView {

    var path: UIBezierPath? { didSet { setNeedsDisplay() } }
    var pathColor: UIColor = .blue { didSet { setNeedsDisplay() } }

    override func draw(_ rect: CGRect) {
    // stroke the path

    pathColor.setStroke()
    path?.stroke()
    }

    }

    And add it to your view hierarchy:

    let pathView = PathView()
    pathView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(pathView)

    NSLayoutConstraint.activate([
    pathView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    pathView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    pathView.topAnchor.constraint(equalTo: view.topAnchor),
    pathView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])

    pathView.backgroundColor = .clear

    let path = UIBezierPath()
    path.move(to: CGPoint(x: 10, y: 10))
    path.addLine(to: CGPoint(x: 100, y: 100))
    path.lineWidth = 3

    pathView.path = path

    Above, I'm adding PathView programmatically, but you can add it via IB, too, and just set its path programmatically.

Draw a line that can stretch like the Xcode assistant editor in Swift

You can use UIPanGestureRecognizer to get gesture events and draw a CALayer with UIBezierPath.

UIPanGestureRecognizer has some gesture states, in this case, we need to handle three states to draw the line. Let's separate the whole action into small pieces for more easier to figure out what to do.

Before the start, there is one thing you have to know.

// We can get current touch position via gesture recognizer.
let currentPanPoint = panRecognizer.location(in: self.view)
  1. To get line start point and create a CALayer in state UIGestureRecognizerState.began.
case .began:
panGestureStartPoint = currentPanPoint
self.view.layer.addSublayer(lineShape)

  1. Get line end point in state UIGestureRecognizerState.changed and create a UIBezierPath, assign the CGPath of UIBezierPath to CALayer to draw the line.
case .changed:
let linePath = UIBezierPath()
linePath.move(to: panGestureStartPoint)
linePath.addLine(to: currentPanPoint)

lineShape.path = linePath.cgPath

  1. Remove the line from layout in state UIGestureRecognizerState.end.
case .ended:
lineShape.path = nil
lineShape.removeFromSuperlayer()

Combine the fragments above, here is the example code.

class ViewController: UIViewController {
@IBOutlet var dragFrom: UILabel!

private lazy var lineShape: CAShapeLayer = {
let lineShape = CAShapeLayer()
lineShape.strokeColor = UIColor.blue.cgColor
lineShape.lineWidth = 2.0

return lineShape
}()
private var panGestureStartPoint: CGPoint = .zero
private lazy var panRecognizer: UIPanGestureRecognizer = {
return UIPanGestureRecognizer(target: self, action: #selector(panGestureCalled(_:)))
}()

override func viewDidLoad() {
super.viewDidLoad()

self.dragFrom.addGestureRecognizer(panRecognizer)
}

// MARK: Selectors
func panGestureCalled(_: UIPanGestureRecognizer) {
let currentPanPoint = panRecognizer.location(in: self.view)
switch panRecognizer.state {
case .began:
panGestureStartPoint = currentPanPoint
self.view.layer.addSublayer(lineShape)

case .changed:
let linePath = UIBezierPath()
linePath.move(to: panGestureStartPoint)
linePath.addLine(to: currentPanPoint)

lineShape.path = linePath.cgPath
case .ended:
lineShape.path = nil
lineShape.removeFromSuperlayer()
default: break
}
}
}

And it works like this.
http://i.imgur.com/5JsFeoB.gifv

If you wanna learn more details, this is the tutorial in Apple's Developer guides. Learn how to draw shapes using Bezier Path

How to draw a line between two points over an image in swift 3?

One option is to add a sub view to your image view and add the line drawing code into its draw(_ rect: CGRect) method.

A sample playground implementation:

class LineView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.init(white: 0.0, alpha: 0.0)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func draw(_ rect: CGRect) {
if let context = UIGraphicsGetCurrentContext() {
context.setStrokeColor(UIColor.blue.cgColor)
context.setLineWidth(3)
context.beginPath()
context.move(to: CGPoint(x: 5.0, y: 5.0)) // This would be oldX, oldY
context.addLine(to: CGPoint(x: 50.0, y: 50.0)) // This would be newX, newY
context.strokePath()
}
}
}

let imageView = UIImageView(image: #imageLiteral(resourceName: "image.png")) // This would be your mapView, here I am just using a random image
let lineView = LineView(frame: imageView.frame)
imageView.addSubview(lineView)

How to add a border just on the top side of a UIView

I consider subclassing UIView and overriding drawRect overkill here. Why not add an extension on UIView and add border subviews?

@discardableResult
func addBorders(edges: UIRectEdge,
color: UIColor,
inset: CGFloat = 0.0,
thickness: CGFloat = 1.0) -> [UIView] {

var borders = [UIView]()

@discardableResult
func addBorder(formats: String...) -> UIView {
let border = UIView(frame: .zero)
border.backgroundColor = color
border.translatesAutoresizingMaskIntoConstraints = false
addSubview(border)
addConstraints(formats.flatMap {
NSLayoutConstraint.constraints(withVisualFormat: $0,
options: [],
metrics: ["inset": inset, "thickness": thickness],
views: ["border": border]) })
borders.append(border)
return border
}

if edges.contains(.top) || edges.contains(.all) {
addBorder(formats: "V:|-0-[border(==thickness)]", "H:|-inset-[border]-inset-|")
}

if edges.contains(.bottom) || edges.contains(.all) {
addBorder(formats: "V:[border(==thickness)]-0-|", "H:|-inset-[border]-inset-|")
}

if edges.contains(.left) || edges.contains(.all) {
addBorder(formats: "V:|-inset-[border]-inset-|", "H:|-0-[border(==thickness)]")
}

if edges.contains(.right) || edges.contains(.all) {
addBorder(formats: "V:|-inset-[border]-inset-|", "H:[border(==thickness)]-0-|")
}

return borders
}

// Usage:
view.addBorder(edges: [.all]) // All with default arguments
view.addBorder(edges: [.top], color: .green) // Just Top, green, default thickness
view.addBorder(edges: [.left, .right, .bottom], color: .red, thickness: 3) // All except Top, red, thickness 3

With this code you're not tied to your subclass too, you can apply it to anything and everything that inherits from UIView - reusable in your project, and any others. Pass in other arguments to your methods to define other colours and widths. Many options.



Related Topics



Leave a reply



Submit