Sangat mudah untuk menggambar garis putus - putus dengan UIKit. Begitu:
CGFloat dashes[] = {4, 2};
[path setLineDash:dashes count:2 phase:0];
[path stroke];
Apakah ada cara untuk menggambar garis putus-putus yang asli?
Ada ide?
Karena pertanyaan ini benar-benar tua dan tidak ada yang dimasukkan secara lengkap @IBDesignable
solusi , ini dia ...
Semoga ini menghemat waktu mengetik seseorang.
@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 mengubahnya.
Taruh saja UIView di tempat kejadian; buat lebar apa pun yang Anda inginkan dan itu akan menjadi lebar garis putus-putus.
Cukup ubah kelas menjadi DottedVertical
dan Anda selesai. Ini akan ditampilkan seperti itu dengan benar di storyboard.
Perhatikan bahwa kode contoh yang diberikan untuk tinggi blok ("totalCount" dan seterusnya ...) menghasilkan blok dengan sempurna, ke piksel, cocok dengan ujung UIView yang membuat garis.
Pastikan untuk mencentang jawaban RobMayoff di bawah ini yang memberikan dua baris kode yang diperlukan untuk titik-bukan-blok.
Jawaban:
Atur gaya tutup garis menjadi bulat dan atur panjang "on" menjadi angka kecil.
Contoh taman 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:
Untuk objektif-C, menggunakan kelas contoh yang sama seperti dalam pertanyaan, cukup tambahkan
CGContextSetLineCap(cx, kCGLineCapRound);
sebelum panggilan ke
CGContextStrokePath
, dan ubah nilaira
array agar sesuai dengan kode Swift saya.sumber
0.01
memberi Anda titik melingkar, sedangkan mereka sedikit memanjang saat menggunakan0
.Versi Objective-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();
sumber
Menggunakan ekstensi UIView, 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 setelah
viewDidLoad
, sepertiviewDidLayoutSubviews
, jalankanaddDashedBorder
fungsi pada tampilan yang dimaksud: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) } }
sumber
Halo teman-teman, solusi ini bekerja untuk saya dengan baik. Saya menemukan suatu tempat dan mengubah sedikit 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 } }
Inilah hasilnya:
sumber
Saya bekerja sedikit pada solusi yang diterima rob mayoff untuk dengan mudah menyesuaikan garis putus-putus:
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 gambarnya:
UIImage.dottedLine(radius: 100, space: 2, numberOfPattern: 1)
sumber
Bukan jawaban lengkap, hanya jawaban yang sangat penting yang yang dikemukakan James P dalam komentar pada jawaban favorit:
Dia menulis:
Sebagai contoh,
let dashes: [CGFloat] = [0.001, path.lineWidth * 2]
sumber
Di swift 3.1 Anda dapat menggunakan kode di bawah ini:
Memiliki tiga gaya:
/* Line cap styles. */ public enum CGLineCap : Int32 { case butt case round case square }
sumber
Bekerja dengan baik dengan kode di bawah ini,
layer.path = linePath.cgPath layer.lineWidth = 3 layer.lineDashPattern = [1,layer.lineWidth*2] as [NSNumber] layer.lineCap = "round"
sumber
Hei, mungkin sudah terlambat untuk menjawab pertanyaan itu. tetapi jika Anda setuju, saya ingin membagikan cara mudah untuk menyelesaikannya kepada pengembang yang mungkin akan menghadapi masalah itu di masa mendatang. jadi saya rasa itu solusi termudah menggunakan @IBDesignable. Anda hanya perlu membuat kelas itu
import UIKit @IBDesignable class DottedVertical: UIView { @IBInspectable var dotColor: UIColor = UIColor.red @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 //DASHED SIMPLE LINE //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 * 1.1] path.lineCapStyle = CGLineCap.round path.setLineDash(dashes, count: dashes.count, phase: 0) dotColor.setStroke() path.stroke() } }
Dan kemudian tambahkan ke tampilan Anda di papan cerita seperti itu
Setelah Anda selesai, Anda dapat menyesuaikan ruang antara lapisan dari baris ini
let dashes: [CGFloat] = [0.0, itemLength * 1.1]
-> Baris 39 di kelas DottedVertical. atau jika Anda ingin menyesuaikan lebar layer, Anda hanya perlu mengedit lebar tampilan garis dari storyboard Andasumber
Saya telah mengimplementasikan potongan kode berikut untuk menambahkan batas dengan gaya titik-titik di bagian bawah
titleLabel
(UILabel
) diviewDidAppear
: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
sumber