ड्राडर्ड (धराशायी नहीं!) लाइन, IBDesignable के साथ 2017 में


86

UIKit के साथ धराशायी रेखा खींचना आसान है । इसलिए:

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

यहां छवि विवरण दर्ज करें

क्या कोई तरीका है एक वास्तविक बिंदीदार रेखा खींचने का?

यहां छवि विवरण दर्ज करें

कोई विचार?


चूंकि यह प्रश्न वास्तव में पुराना है और कोई भी पूर्ण @IBDesignableसमाधान में नहीं लगाया गया है , यहां यह है ...

आशा है कि यह किसी को टाइपिंग बचाता है।

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

मैंने इसे लंबवत बनाया, आप आसानी से बदल सकते हैं।

यहां छवि विवरण दर्ज करें

बस दृश्य में एक UIView डाल दिया; आप इसे जिस भी चौड़ाई में चाहते हैं, बनाएं और यह बिंदीदार रेखा की चौड़ाई होगी।

बस कक्षा को बदलें DottedVerticalऔर आपका काम हो गया। यह स्टोरीबोर्ड में ठीक तरह से प्रस्तुत करेगा।

यहां छवि विवरण दर्ज करें

ध्यान दें कि ब्लॉकों की ऊंचाई के लिए दिया गया उदाहरण कोड ("TotalCount" और इसी तरह ...) ब्लॉकों में पूरी तरह से परिणाम करता है, पिक्सेल के लिए, लाइन बनाने वाले UIView के सिरों के साथ मेल खाता है।

नीचे RobMayoff के उत्तर पर टिक करना सुनिश्चित करें जो डॉट्स-नहीं-ब्लॉक के लिए कोड की दो आवश्यक लाइनें देता है।


यहाँ विकर्ण लाइनों को आकर्षित करने के लिए एक शानदार तरीका है! :) stackoverflow.com/a/45228178/294884
fattie

धन्यवाद Fattie, मैंने देखने की ऊंचाई के अनुसार डॉट्स काउंट बनाने के लिए थोड़ा संशोधन के साथ प्रयोग किया, कुल डायनेमिकिकडॉट्स = सीमाएं। Size.height / CGFloat (3); आइए ItemLength = fullHeight / TotalDynamicDots
Nitesh

क्या हमारे पास इसका एक क्षैतिज संस्करण हो सकता है? @ फटी
मोहम्मद एस

जवाबों:


97

गोल करने के लिए लाइन कैप स्टाइल सेट करें और "ऑन" लंबाई को एक छोटी संख्या पर सेट करें।

स्विफ्ट खेल का मैदान उदाहरण:

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

परिणाम:

डॉट्स


वस्तुनिष्ठ-सी के लिए, प्रश्न में उसी उदाहरण वर्ग का उपयोग करके, बस जोड़ें

CGContextSetLineCap(cx, kCGLineCapRound);

कॉल करने से पहले CGContextStrokePath, और raमेरे स्विफ्ट कोड से मिलान करने के लिए ऐरे वैल्यू में बदलाव करें ।


9
मुख्य जानकारी मेरे उत्तर की पहली (अंग्रेजी पाठ) पंक्ति में है। बाकी सब ग्रेवी है।
लूटना

5
मैंने 0.01आपको एक गोलाकार बिंदी देने के लिए लंबाई पर स्थापित किया है , जबकि उपयोग करते समय वे थोड़ा लम्बी हैं 0
जेम्स पी

मैंने एक स्क्रीन शॉट (डिफ़ॉल्ट सिस्टम-वाइड शॉर्टकट: .4) लेकर उस छवि को बनाया। वहाँ Xcode में एक अंतर्निहित कैप्चर सुविधा नहीं है जो मुझे पता है।
लूटना

2
जेम्स पी की सलाह अमूल्य है। इस कीड़े ने मुझे इतना दिल-दर्द और काम दिया है। धन्यवाद जेम्स। मैं एक अर्ध-उत्तर बनाऊंगा, ताकि लोग इसे और अधिक स्पष्ट रूप से देख सकें।
वूमबेल

1
मैंने अपना उत्तर बग वर्कअवे और नवीनतम स्विफ्ट सिंटैक्स के साथ अद्यतन किया है।
लूट

13

ऊपर दिए गए स्विफ्ट उदाहरण का उद्देश्य-सी संस्करण:

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

11

UIView एक्सटेंशन का उपयोग करके, स्विफ्ट 3.0 के साथ संगत निम्नलिखित काम करना चाहिए:

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

}

इसके बाद चलने वाले फ़ंक्शन में viewDidLoad, जैसे viewDidLayoutSubviews, addDashedBorderप्रश्न में दृश्य पर फ़ंक्शन चलाएँ :

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

}

1
यह एक धराशायी रेखा (यानी, आयत) बनाता है, लेकिन आप एक बिंदीदार (यानी, मंडलियां) रेखा कैसे बनाते हैं?
Crashalot

4

हैलो दोस्तों इस समाधान मेरे लिए ठीक काम किया। मैंने कहीं पाया और कंसोल चेतावनी को रोकने के लिए थोड़ा बदल दिया।

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

यह परिणाम है:

परिणाम


3

मैं आसानी से बिंदीदार रेखा को कस्टमाइज़ करने के लिए रॉब मयॉफ़ स्वीकार किए गए समाधान पर थोड़ा काम करता हूं:

  • प्रत्येक वृत्त की त्रिज्या बदलें।
  • 2 हलकों के बीच रिक्त स्थान की संख्या बदलें।
  • पैटर्न की संख्या को उत्पन्न करने के लिए बदलें।

फ़ंक्शन एक 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

    }
}

और यहाँ है कि छवि कैसे प्राप्त करें:

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

2

पूर्ण उत्तर नहीं, बस एक बहुत ही महत्वपूर्ण गोटका है जो जेम्स पी ने पसंदीदा उत्तर पर एक टिप्पणी में उठाया:

उसने लिखा:

मैंने पाया है कि 0.01 पर लंबाई निर्धारित करना आपको एक गोलाकार बिंदी देता है, जबकि 0 का उपयोग करते समय वे थोड़े लम्बे होते हैं।

उदाहरण के लिए,

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

0

स्विफ्ट 3.1 में आप नीचे दिए गए कोड का उपयोग कर सकते हैं:

context.setLineCap(.round)

तीन शैलियों है:

 /* Line cap styles. */

public enum CGLineCap : Int32 {

    case butt

    case round

    case square
}

0

नीचे दिए गए कोड के साथ काम करना ठीक है,

layer.path = linePath.cgPath
layer.lineWidth = 3
layer.lineDashPattern = [1,layer.lineWidth*2] as [NSNumber]
layer.lineCap = "round"

0

अरे शायद उस सवाल पर जवाब देने में बहुत देर हो चुकी है। लेकिन अगर आप सहमत हैं तो मैं एक आसान तरीका साझा करना चाहूंगा जो कि डेवलपर्स के लिए हल हो सकता है जो भविष्य में उस समस्या का सामना करेंगे। इसलिए मुझे लगता है कि @IBDesignable का उपयोग करके सबसे आसान समाधान है। आपको बस उस वर्ग को बनाने की जरूरत है

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

और फिर इसे स्टोरीबोर्ड में अपने विचार के समान जोड़ दें यहां छवि विवरण दर्ज करें

एक बार जब आप ठंडा कर लेते हैं तो इस लाइन से परतों के बीच के स्थान को अनुकूलित करते हैं let dashes: [CGFloat] = [0.0, itemLength * 1.1] -> रेखाविहीन कक्षा में लाइन 39। या यदि आप अपनी स्टोरीबोर्ड से अपनी लाइन व्यू चौड़ाई संपादित करने के लिए केवल उस लेयर की चौड़ाई को कस्टमाइज़ करना चाहते हैं


-1

मैंने नीचे titleLabel( UILabel) के नीचे में बिंदीदार शैली के साथ सीमा जोड़ने के लिए निम्नलिखित कोड को लागू किया है 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];

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


जब मैं आपके कोड का उपयोग करता हूं, तो यह वर्ग नहीं, मंडलियां बना रहा है।
15

मूव को बदलने की कोशिश करें। अपनी आवश्यकता के अनुसार, AddLineToPoint, linewidth और lineDashPattern मान
जोड़ें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.