Pertanyaan Gambarkan garis putus-putus (tidak putus-putus!), Dengan IBDesignable pada tahun 2017


Sangat mudah untuk menggambar putus-putus Sejalan dengan UIKit. Begitu:

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

enter image description here

Adakah cara untuk menggambar garis putus-putus yang asli?

enter image description here

Ada ide?


Karena pertanyaan ini benar-benar sudah tua dan tidak ada yang dimasukkan secara penuh @IBDesignable solusi, ini dia ...

Berharap itu menyelamatkan seseorang yang mengetik.

@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()
    }
}

Saya membuatnya vertikal, Anda dapat dengan mudah berubah.

enter image description here

Hanya menempatkan UIView di tempat kejadian; buatlah lebar apa pun yang Anda inginkan dan itu akan menjadi lebar garis putus-putus.

Cukup ubah kelas menjadi DottedVertical dan selesai. Ini akan merender seperti itu dengan benar di storyboard.

enter image description here

Perhatikan bahwa kode contoh yang diberikan untuk ketinggian blok ("totalCount" dan seterusnya ...) menghasilkan blok sempurna, ke piksel, sesuai dengan ujung UIView yang menciptakan garis.

Pastikan untuk memberikan jawaban RobMayoff di bawah ini yang memberikan dua baris kode yang diperlukan untuk titik-bukan-blok.


76
2017-09-24 13:34


asal


Jawaban:


Setel gaya garis garis untuk membulatkan dan atur panjang “on” ke angka yang kecil.

Contoh tempat bermain cepat:

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()

Hasil:

dots


Untuk tujuan-C, menggunakan kelas contoh yang sama seperti pada pertanyaan, cukup tambahkan

CGContextSetLineCap(cx, kCGLineCapRound);

sebelum panggilan ke CGContextStrokePath, dan ubah ra nilai larik untuk mencocokkan kode Swift saya.


84
2017-09-24 14:41



Versi obyektif-C dari contoh Swift di atas:

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



Menggunakan ekstensi UIView, yang kompatibel dengan Swift 3.0 berikut ini seharusnya berfungsi:

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)
    }

}

Kemudian dalam fungsi yang berjalan sesudahnya viewDidLoad, suka viewDidLayoutSubviews, jalankan addDashedBorder berfungsi pada tampilan yang dipermasalahkan:

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



Halo teman-teman solusi ini bekerja untuk saya baik-baik saja. Saya menemukan suatu tempat dan sedikit berubah untuk mencegah peringatan konsol.

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
    }
}

Ini hasilnya:

result


3
2018-01-20 08:48



Saya bekerja sedikit pada solusi rob mayoff diterima untuk dengan mudah menyesuaikan garis putus-putus:

  • ubah radius setiap lingkaran.
  • ubah jumlah spasi antara 2 lingkaran.
  • ubah jumlah pola yang akan dihasilkan.

Fungsi mengembalikan 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

    }
}

Dan inilah cara mendapatkan gambar:

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

2
2018-05-12 17:03



Bukan jawaban penuh, hanya sangat gotcha penting bahwa James P mengangkat komentar pada jawaban favorit:

Dia menulis:

Saya telah menemukan pengaturan panjang untuk 0,01 memberi Anda titik melingkar,   sedangkan mereka sedikit memanjang saat menggunakan 0.

Sebagai contoh,

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

1
2018-02-24 02:42



Dalam kecepatan 3.1 Anda dapat menggunakan kode di bawah ini:

context.setLineCap(.round)

Memiliki tiga gaya:

 /* Line cap styles. */

public enum CGLineCap : Int32 {

    case butt

    case round

    case square
}

0
2018-05-22 06:50



Saya telah menerapkan potongan kode berikut untuk menambahkan perbatasan dengan gaya bertitik di bagian bawah titleLabel (UILabel) di 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];

Refrensi: https://gist.github.com/kaiix/4070967


-1
2018-04-29 07:16