Câu hỏi Vẽ đường chấm (không đứt nét!), Với IBDesignable vào năm 2017


Thật dễ dàng để vẽ rạng ngời phù hợp với UIKit. Vì thế:

CGFloat dashes[] = {4, 2};
[path setLineDash:dashes count:2 phase:0];
[path stroke];

enter image description here

Có cách nào để vẽ một đường chấm chấm chính hãng không?

enter image description here

Bất kỳ ý tưởng?


Vì câu hỏi này thực sự cũ và không ai đặt đầy đủ @IBDesignable giải pháp, ở đây là ...

Hy vọng nó sẽ tiết kiệm một số người gõ.

@IBDesignable class DottedVertical: UIView {

    @IBInspectable var dotColor: UIColor = UIColor.etc
    @IBInspectable var lowerHalfOnly: Bool = false

    override func draw(_ rect: CGRect) {

        // say you want 8 dots, with perfect fenceposting:
        let totalCount = 8 + 8 - 1
        let fullHeight = bounds.size.height
        let width = bounds.size.width
        let itemLength = fullHeight / CGFloat(totalCount)

        let path = UIBezierPath()

        let beginFromTop = CGFloat(0.0)
        let top = CGPoint(x: width/2, y: beginFromTop)
        let bottom = CGPoint(x: width/2, y: fullHeight)

        path.move(to: top)
        path.addLine(to: bottom)

        path.lineWidth = width

        let dashes: [CGFloat] = [itemLength, itemLength]
        path.setLineDash(dashes, count: dashes.count, phase: 0)

        // for ROUNDED dots, simply change to....
        //let dashes: [CGFloat] = [0.0, itemLength * 2.0]
        //path.lineCapStyle = CGLineCap.round

        dotColor.setStroke()
        path.stroke()
    }
}

Tôi làm cho nó thẳng đứng, bạn có thể dễ dàng thay đổi.

enter image description here

Chỉ cần đặt một UIView trong cảnh; làm cho nó bất kể chiều rộng bạn muốn và đó sẽ là chiều rộng của đường chấm chấm.

Chỉ cần thay đổi lớp học thành DottedVertical và bạn đã hoàn tất. Nó sẽ hiển thị như thế đúng trong bảng phân cảnh.

enter image description here

Lưu ý rằng mã ví dụ được đưa ra cho chiều cao của các khối ("totalCount" và vv ..) kết quả trong các khối hoàn hảo, với pixel, phù hợp với các đầu của UIView đang tạo dòng.

Hãy chắc chắn để đánh dấu câu trả lời của RobMayoff dưới đây cung cấp cho hai dòng mã cần thiết cho các chấm không-khối.


76
2017-09-24 13:34


gốc


đây là một cách tuyệt vời để vẽ đường chéo! :) stackoverflow.com/a/45228178/294884 - Fattie
Cảm ơn Fattie, tôi đã sử dụng với ít sửa đổi để làm cho các chấm đếm theo chiều cao của khung nhìn, hãy để totalDynamicDots = bounds.size.height / CGFloat (3); cho phép itemLength = fullHeight / totalDynamicDots - Nitesh
siêu !, @Nitesh tận hưởng ... - Fattie


Các câu trả lời:


Đặt kiểu nắp đường kẻ tròn và đặt chiều dài “bật” thành một số nhỏ.

Ví dụ về sân chơi Swift:

import UIKit
import PlaygroundSupport

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

let dashes: [CGFloat] = [0.001, path.lineWidth * 2]
path.setLineDash(dashes, count: dashes.count, phase: 0)
path.lineCapStyle = CGLineCap.round

UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2)

UIColor.white.setFill()
UIGraphicsGetCurrentContext()!.fill(.infinite)

UIColor.black.setStroke()
path.stroke()

let image = UIGraphicsGetImageFromCurrentImageContext()
let view = UIImageView(image: image)
PlaygroundPage.current.liveView = view

UIGraphicsEndImageContext()

Kết quả:

dots


Đối với mục tiêu-C, sử dụng cùng một lớp ví dụ như trong câu hỏi, chỉ cần thêm

CGContextSetLineCap(cx, kCGLineCapRound);

trước cuộc gọi đến CGContextStrokePathvà thay đổi ra giá trị mảng để khớp với mã Swift của tôi.


84
2017-09-24 14:41



Thông tin chính nằm trong dòng đầu tiên (văn bản tiếng Anh) của câu trả lời của tôi. Phần còn lại là nước thịt. - rob mayoff
Tôi đã tìm thấy thiết lập độ dài trên 0.01cung cấp cho bạn một dấu chấm tròn, trong khi chúng hơi dài khi sử dụng 0. - James P
Tôi đã tạo hình ảnh đó bằng cách chụp ảnh màn hình (phím tắt toàn hệ thống mặc định: ⌘⇧4). Chưa bao giờ có một cơ sở chụp tích hợp trong Xcode mà tôi biết. - rob mayoff
Lời khuyên của James P là vô giá. Lỗi này đã khiến tôi rất đau lòng và làm việc. Cảm ơn James. Tôi sẽ tạo một câu trả lời bán, để mọi người có thể thấy rõ hơn. - Womble
Tôi đã cập nhật câu trả lời của mình với cách giải quyết lỗi và cú pháp Swift mới nhất. - rob mayoff


Phiên bản Objective-C của ví dụ Swift ở trên:

UIBezierPath * path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(290.0, 10.0)];
[path setLineWidth:8.0];
CGFloat dashes[] = { path.lineWidth, path.lineWidth * 2 };
[path setLineDash:dashes count:2 phase:0];
[path setLineCapStyle:kCGLineCapRound];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 20), false, 2);
[path stroke];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

13
2017-07-29 10:54





Sử dụng phần mở rộng UIView, tương thích với Swift 3.0, những thứ sau đây sẽ hoạt động:

extension UIView {

    func addDashedBorder(strokeColor: UIColor, lineWidth: CGFloat) {
        self.layoutIfNeeded()
        let strokeColor = strokeColor.cgColor

        let shapeLayer:CAShapeLayer = CAShapeLayer()
        let frameSize = self.frame.size
        let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: frameSize.height)

        shapeLayer.bounds = shapeRect
        shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2)
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = strokeColor
        shapeLayer.lineWidth = lineWidth
        shapeLayer.lineJoin = kCALineJoinRound

        shapeLayer.lineDashPattern = [5,5] // adjust to your liking
        shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: shapeRect.width, height: shapeRect.height), cornerRadius: self.layer.cornerRadius).cgPath

        self.layer.addSublayer(shapeLayer)
    }

}

Sau đó, trong một hàm chạy sau viewDidLoad, như viewDidLayoutSubviews, chạy addDashedBorder chức năng trên chế độ xem được đề cập:

class ViewController: UIViewController {

    var someView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        someView = UIView()
        someView.layer.cornerRadius = 5.0

        view.addSubview(someView)

        someView.translatesAutoresizingMaskIntoConstraints = false
        someView.widthAnchor.constraint(equalToConstant: 200).isActive = true
        someView.heightAnchor.constraint(equalToConstant: 200).isActive = true
        someView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        someView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }

    override func viewDidLayoutSubviews() {
        someView.addDashedBorder(strokeColor: UIColor.red, lineWidth: 1.0)
    }

}

10
2017-09-28 15:58



Điều này tạo ra một đường đứt nét (tức là, hình chữ nhật), nhưng làm thế nào để bạn tạo một đường chấm chấm (tức là, vòng tròn)? - Crashalot


Xin chào các bạn giải pháp này đã làm việc tốt cho tôi. Tôi tìm thấy một nơi nào đó và thay đổi một chút để ngăn chặn cảnh báo console.

extension UIImage {
    static func drawDottedImage(width: CGFloat, height: CGFloat, color: UIColor) -> UIImage {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 1.0, y: 1.0))
        path.addLine(to: CGPoint(x: width, y: 1))
        path.lineWidth = 1.5           
        let dashes: [CGFloat] = [path.lineWidth, path.lineWidth * 5]
        path.setLineDash(dashes, count: 2, phase: 0)
        path.lineCapStyle = .butt
        UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 2)
        color.setStroke()
        path.stroke()

        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return image
    }
}

Đây là kết quả:

result


3
2018-01-20 08:48





Tôi làm việc một chút về cướp mayoff chấp nhận giải pháp để dễ dàng tùy chỉnh các đường chấm chấm:

  • thay đổi bán kính của mỗi vòng tròn.
  • thay đổi số lượng khoảng cách giữa 2 vòng tròn.
  • thay đổi số lượng mẫu để tạo.

Hàm trả về một UIImage:

extension UIImage {

    class func dottedLine(radius radius: CGFloat, space: CGFloat, numberOfPattern: CGFloat) -> UIImage {


        let path = UIBezierPath()
        path.moveToPoint(CGPointMake(radius/2, radius/2))
        path.addLineToPoint(CGPointMake((numberOfPattern)*(space+1)*radius, radius/2))
        path.lineWidth = radius

        let dashes: [CGFloat] = [path.lineWidth * 0, path.lineWidth * (space+1)]
        path.setLineDash(dashes, count: dashes.count, phase: 0)
        path.lineCapStyle = CGLineCap.Round


        UIGraphicsBeginImageContextWithOptions(CGSizeMake((numberOfPattern)*(space+1)*radius, radius), false, 1)
        UIColor.whiteColor().setStroke()
        path.stroke()
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image

    }
}

Và đây là cách để có được hình ảnh:

UIImage.dottedLine(radius: 100, space: 2, numberOfPattern: 1)

2
2018-05-12 17:03





Không phải là câu trả lời đầy đủ, chỉ là một quan trọng gotcha rằng James P đã nêu ra một bình luận về câu trả lời yêu thích:

Anh đã viết:

Tôi đã tìm thấy thiết lập độ dài trên 0,01 cung cấp cho bạn một dấu chấm tròn,   trong khi chúng hơi dài khi sử dụng 0.

Ví dụ,

   let dashes: [CGFloat] = [0.001, path.lineWidth * 2]

1
2018-02-24 02:42





Trong nhanh chóng 3.1 bạn có thể sử dụng mã dưới đây:

context.setLineCap(.round)

Có ba kiểu:

 /* Line cap styles. */

public enum CGLineCap : Int32 {

    case butt

    case round

    case square
}

0
2018-05-22 06:50





Tôi đã triển khai đoạn mã sau để thêm đường viền với kiểu chấm chấm ở cuối titleLabel (UILabel) trong viewDidAppear:

CAShapeLayer *shapelayer = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0.0, titileLabel.frame.size.height-2)];
[path addLineToPoint:CGPointMake(SCREEN_WIDTH, titileLabel.frame.size.height-2)];
UIColor *fill = [UIColor colorWithRed:0.80f green:0.80f blue:0.80f alpha:1.00f];
shapelayer.strokeStart = 0.0;
shapelayer.strokeColor = fill.CGColor;
shapelayer.lineWidth = 2.0;
shapelayer.lineJoin = kCALineJoinRound;
shapelayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:2],[NSNumber numberWithInt:3 ], nil];
shapelayer.path = path.CGPath;

[titileLabel.layer addSublayer:shapelayer];

Làm mát: https://gist.github.com/kaiix/4070967


-1
2018-04-29 07:16



đây là tạo hình vuông, không phải hình tròn, khi tôi sử dụng mã của bạn. - helloB
thử thay đổi các giá trị moveToPoint, addLineToPoint, linewidth và lineDashPattern theo yêu cầu của bạn - iAkki
Không hoạt động, bạn đã kiểm tra chưa? - LightNight