简体   繁体   中英

How to draw a dash line border for NSView

In my custom view, i have code as below:

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

     //Drawing code here.
    [self setWantsLayer: YES];
    [self.layer setBorderWidth: 1];

    [self.layer setBorderColor:[NSColor colorWithRed:205/255.0 green:211/255.0 blue:232/255.0 alpha:1.0].CGColor];
    [self.layer setCornerRadius: 10];
}

This is OK to set border line and color for my NSView, but i want to set a dash line, anyone know how to do this? And i tried some codes from the web search, but it doens't draw a border at all.

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    // Drawing code here.
    CGFloat dashPattern[] = {10,4}; //make your pattern here
    NSBezierPath *textViewSurround = [NSBezierPath bezierPathWithRoundedRect:self.frame xRadius:10 yRadius:10];
    [textViewSurround setLineWidth:2.0f];
    [textViewSurround setLineDash:dashPattern count:2 phase:0];
    [[NSColor colorWithRed:205/255.0 green:211/255.0 blue:232/255.0 alpha:1.0] set];
    [textViewSurround stroke];
}

here is a complete example using a subclass of NSView in Swift 3:

class BorderedView: NSView {
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // dash customization parameters
        let dashHeight: CGFloat = 3
        let dashLength: CGFloat = 10
        let dashColor: NSColor = .red

        // setup the context
        let currentContext = NSGraphicsContext.current()!.cgContext
        currentContext.setLineWidth(dashHeight)
        currentContext.setLineDash(phase: 0, lengths: [dashLength])
        currentContext.setStrokeColor(dashColor.cgColor)

        // draw the dashed path
        currentContext.addRect(bounds.insetBy(dx: dashHeight, dy: dashHeight))
        currentContext.strokePath()
    }
}

You can do this through CGContext Here is an answer that worked for me:

how to make dashed line moveable

And my result:

在此处输入图片说明

In case you want to setup line border with CAShapeLayer (Swift 4.2):

class StrokeWithDashedLineView: NSView {

   private let shapeLayer = CAShapeLayer()
   private let fillLayer = CALayer()
   private let textLabel = NSTextField().autolayoutView()

   override init(frame frameRect: NSRect) {
      super.init(frame: frameRect)
      setupUI()
      setupLayout()
   }

   required init?(coder decoder: NSCoder) {
      fatalError()
   }

   override var intrinsicContentSize: NSSize {
      return CGSize(intrinsicHeight: 76)
   }

   override func layout() {
      super.layout()
      updateLayers()
   }

   private func updateLayers() {
      layer?.cornerRadius = 0.5 * bounds.height // Making ourselves rounded.

      // Stroke Layer
      let shapeBounds = CGRect(width: bounds.width - shapeLayer.lineWidth, height: bounds.height - shapeLayer.lineWidth)
      let shapeRadius = 0.5 * shapeBounds.height
      let path = CGMutablePath()
      path.addRoundedRect(in: shapeBounds, cornerWidth: shapeRadius, cornerHeight: shapeRadius)
      shapeLayer.path = path
      shapeLayer.bounds = shapeBounds
      shapeLayer.position = CGPoint(x: 0.5 * shapeLayer.lineWidth, y: 0.5 * shapeLayer.lineWidth)

      // Fill Layer
      let fillBounds = CGRect(width: bounds.width - 2 * shapeLayer.lineWidth, height: bounds.height - 2 * shapeLayer.lineWidth)
      fillLayer.cornerRadius = 0.5 * fillBounds.height
      fillLayer.bounds = fillBounds
      fillLayer.position = CGPoint(x: shapeLayer.lineWidth, y: shapeLayer.lineWidth)
   }

   private func setupUI() {
      wantsLayer = true
      layer?.masksToBounds = true

      shapeLayer.lineWidth = 3
      shapeLayer.strokeColor = NSColor.red.cgColor
      shapeLayer.fillColor = nil
      shapeLayer.lineDashPattern = [11.2, 11.2]
      shapeLayer.lineCap = .round
      shapeLayer.anchorPoint = .zero

      fillLayer.backgroundColor = NSColor.yellow.cgColor
      fillLayer.anchorPoint = .zero

      layer?.addSublayer(shapeLayer)
      layer?.addSublayer(fillLayer)

      addSubview(textLabel)

      textLabel.text = "Drag Xib or Storyboard files onto\nthis window to open them"
      textLabel.alignment = .center
      textLabel.textColor = .black
      textLabel.font = NSFont.semibold(size: 13)
      textLabel.isEditable = false
      textLabel.drawsBackground = false
      textLabel.isBezeled = false
   }

   private func setupLayout() {
      textLabel.centerXAnchor.constraint(equalTo: centerXAnchor).activate()
      textLabel.centerYAnchor.constraint(equalTo: centerYAnchor).activate()
   }
}

Result:

CAShapeLayer的窗口

You can do this like,

[yourView.layer setBorderWidth:5.0];
[yourView.layer setBorderColor:[[UIColor colorWithPatternImage:[UIImage imageNamed:@"DotedImage.png"]] CGColor]];

Add dashed image in project and import QuartzCore/QuartzCore.h in project,

#import <QuartzCore/QuartzCore.h>

Update :

Image size and View size should be same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM