आप किसी व्यू कंट्रोलर से प्रोग्राम लाइन कैसे बनाते हैं?


82

मेरे पास ए UIViewController। मैं अपने प्रोग्राम प्रोग्राम में से किसी एक दृश्य में एक रेखा कैसे खींच सकता हूं?


2
नहीं, तुम नहीं कर सकते। ड्रॉइंग को कंट्रोलर द्वारा देखा जाना चाहिए। आपको अपना डिज़ाइन बदलना होगा।
ब्रायन चेन

1
@xlc आप इसे VC से कर सकते हैं, जैसा कि रोब के उत्तर से पता चलता है। यदि आप वास्तव में मददगार बनना चाहते हैं, तो बताएं कि बेजियर तकनीक में क्या नुकसान है।
mkc842

क्या हम कुछ कोड देख सकते हैं? मैं सहमत हूं, यह एक वास्तविक प्रश्न है, लेकिन मैं (शायद हम) कोड का सबसे अच्छा जवाब देते हैं कि आप किस बारे में बात कर रहे हैं।
बगमग्नेट

जवाबों:


186

दो सामान्य तकनीकें हैं।

  1. का उपयोग कर CAShapeLayer:

    • एक बनाएँ UIBezierPath(निर्देशांक बदलें जो आप चाहते हैं):

      UIBezierPath *path = [UIBezierPath bezierPath];
      [path moveToPoint:CGPointMake(10.0, 10.0)];
      [path addLineToPoint:CGPointMake(100.0, 100.0)];
      
    • एक CAShapeLayerका उपयोग करें कि बनाएँ UIBezierPath:

      CAShapeLayer *shapeLayer = [CAShapeLayer layer];
      shapeLayer.path = [path CGPath];
      shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
      shapeLayer.lineWidth = 3.0;
      shapeLayer.fillColor = [[UIColor clearColor] CGColor];
      
    • CAShapeLayerउसे अपने दृश्य की परत में जोड़ें :

      [self.view.layer addSublayer:shapeLayer];
      

    Xcode के पिछले संस्करणों में, आपको अपने प्रोजेक्ट के "लिंक बाइनरी विद लाइब्रेरीज़" में मैन्युअल रूप से QuartzCore.framework को जोड़ना होगा और <QuartzCore/QuartzCore.h>अपनी .m फ़ाइल में हेडर आयात करना होगा , लेकिन यह अब आवश्यक नहीं है (यदि आपके पास "मॉड्यूल सक्षम करें" और "लिंक" है। फ्रेमवर्क स्वचालित रूप से "बिल्ड सेटिंग्स चालू)।

  2. अन्य तरीका उपवर्ग में है UIViewऔर फिर विधि में CoreGraphics कॉल का उपयोग करें drawRect:

    • एक UIViewउपवर्ग बनाएँ और एक को परिभाषित करें drawRectजो आपकी रेखा खींचता है।

      आप इसे कोर ग्राफिक्स के साथ कर सकते हैं:

      - (void)drawRect:(CGRect)rect {
          CGContextRef context = UIGraphicsGetCurrentContext();
      
          CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
          CGContextSetLineWidth(context, 3.0);
          CGContextMoveToPoint(context, 10.0, 10.0);
          CGContextAddLineToPoint(context, 100.0, 100.0);
          CGContextDrawPath(context, kCGPathStroke);
      }
      

      या उपयोग कर रहा है UIKit:

      - (void)drawRect:(CGRect)rect {
          UIBezierPath *path = [UIBezierPath bezierPath];
          [path moveToPoint:CGPointMake(10.0, 10.0)];
          [path addLineToPoint:CGPointMake(100.0, 100.0)];
          path.lineWidth = 3;
          [[UIColor blueColor] setStroke];
          [path stroke];
      }
      
    • तब आप या तो अपने NIB / स्टोरीबोर्ड या दृश्य के लिए बेस क्लास के रूप में इस व्यू क्लास का उपयोग कर सकते हैं, या आप अपने व्यू कंट्रोलर को प्रोग्रामेटिक रूप से इसे सबव्यू के रूप में जोड़ सकते हैं:

      PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
      pathView.backgroundColor = [UIColor clearColor];
      
      [self.view addSubview: pathView];
      

उपरोक्त दोनों दृष्टिकोणों की स्विफ्ट प्रस्तुतियाँ इस प्रकार हैं:

  1. CAShapeLayer:

    // create path
    
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 10, y: 10))
    path.addLine(to: CGPoint(x: 100, y: 100))
    
    // Create a `CAShapeLayer` that uses that `UIBezierPath`:
    
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = path.cgPath
    shapeLayer.strokeColor = UIColor.blue.cgColor
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineWidth = 3
    
    // Add that `CAShapeLayer` to your view's layer:
    
    view.layer.addSublayer(shapeLayer)
    
  2. UIView उपवर्ग:

    class PathView: UIView {
    
        var path: UIBezierPath?           { didSet { setNeedsDisplay() } }
        var pathColor: UIColor = .blue    { didSet { setNeedsDisplay() } }
    
        override func draw(_ rect: CGRect) {
            // stroke the path
    
            pathColor.setStroke()
            path?.stroke()
        }
    
    }
    

    और इसे अपने दृश्य पदानुक्रम में जोड़ें:

    let pathView = PathView()
    pathView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(pathView)
    
    NSLayoutConstraint.activate([
        pathView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        pathView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        pathView.topAnchor.constraint(equalTo: view.topAnchor),
        pathView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
    
    pathView.backgroundColor = .clear
    
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 10, y: 10))
    path.addLine(to: CGPoint(x: 100, y: 100))
    path.lineWidth = 3
    
    pathView.path = path
    

    ऊपर, मैं PathViewप्रोग्रामेटिक रूप से जोड़ रहा हूं , लेकिन आप इसे आईबी के माध्यम से भी जोड़ सकते हैं, और बस इसे pathप्रोग्रामेटिक रूप से सेट कर सकते हैं ।


@ रोब: यह पूरी तरह से ठीक काम करता है। मैं आपसे पूछना चाहता हूं कि मेरे पास एबी से एक लाइन की दूरी एबी और एक कोण है, फिर उस स्थिति में अंक और अंत कैसे प्राप्त करें? क्रिप्या मेरि सहायता करे।
मंथन

मैंने अपने दृष्टिकोण में अपच को जोड़ा, और यदि मेरे पास उपरोक्त टिप्पणी है तो अगर मैं ऊपर की टिप्पणी में सीधी रेखा को ठीक से काम कर रहा हूं तो जोड़ दें। लेकिन जब मैं बिंदु को छूने से खुद को छूता हूं तो रंग @Rob
किशोर कुमार

जब आप कर सकते हैं CAShapeLayer विधि का उपयोग कर (और संभावना चाहते हैं) लाइन टोपियां गोल करने के लिए सेट करेंगे ताकि लाइनें चिकनी दिखें जैसा कि वे कनेक्ट करते हैं,shapeLayer.lineCap = kCALineCapRound;
अल्बर्ट रेनशॉ

या, यदि आपके पास कई पंक्तियाँ हैं, जिन्हें आप जोड़ना चाहते हैं, तो आप सुचारू रूप से देखना चाहते हैं, आप UIBezierPathबार-बार कॉल addLineToPoint/ addLine(to:)कॉल के साथ भी सिंगल हो सकते हैं। तब आप चुन सकते हैं कि आप पसंद करते हैं shapeLayer.lineJoin = kCALineJoinRoundया kCALineJoinBevelया kCALineJoinMiter
रोब

कोड स्निपेट के लिए धन्यवाद, इसने मुझे कुछ समय बचाया। यदि आप एक गतिशील दृश्य बनाने का इरादा रखते हैं, तो कुछ घटनाओं पर प्रतिक्रिया करते हुए, आपको इसके साथ ड्रॉ की शुरुआत में उपले को साफ करना होगा: self.layer.sublayers = nil
Vilmir

15

एक UIView बनाएं और इसे अपने दृश्य नियंत्रक के दृश्य के उप-भाग के रूप में जोड़ें। आप इस सबव्यू की ऊंचाई या चौड़ाई को बहुत छोटा होने के लिए संशोधित कर सकते हैं ताकि यह एक लाइन की तरह दिखे। यदि आपको एक विकर्ण रेखा खींचने की आवश्यकता है, तो आप सबवेज़ बदलने वाली संपत्ति को संशोधित कर सकते हैं।

जैसे काली क्षैतिज रेखा खींचना। इसे आपके दृश्य नियंत्रक के कार्यान्वयन के भीतर से बुलाया जाता है

UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];

मैं सहमत होना चाहूंगा कि एक विभाजक तत्व के लिए (जैसे UI तत्वों के बीच एक रेखा) यह कम से कम प्रतिरोध का मार्ग है। किसी CoreAnimation लेयर को वापस करने के लिए बिटमैप में रेंडर करने या कस्टम दृश्य में ड्रॉ हैंडलर को लागू करने का विकल्प कहीं अधिक शामिल है। यह शायद हार्डवेयर को बेहतर बनाता है, बशर्ते कि यह केवल एक पंक्ति हो।
मार्को

4
मैं इस तर्क के बारे में उत्सुक हूं कि यह एक भयानक विचार क्यों है। मैं किसी भी समस्या से बचना चाहूंगा, यह समाधान मेरे अपने कोड में हो सकता है।
जेफ एम्स

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

9

स्विफ्ट 3:

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

let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.lineWidth = 3.0

view.layer.addSublayer(shapeLayer)

8

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

अपनी परियोजना में लेख के सामान्य-उद्देश्य दृश्य उपवर्ग को शामिल करें, फिर यह एक तरह का कोड है जिसे आप अपने व्यू कंट्रोलर में उस रेखा पर एक दृश्य बनाने के लिए रख सकते हैं जो एक रेखा खींचता है:

DrawView* drawableView = [[[DrawView alloc] initWithFrame:CGRectMake(0,0,320,50)] autorelease];
drawableView.drawBlock = ^(UIView* v,CGContextRef context)
{
  CGPoint startPoint = CGPointMake(0,v.bounds.size.height-1);
  CGPoint endPoint = CGPointMake(v.bounds.size.width,v.bounds.size.height-1);

  CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
  CGContextSetLineWidth(context, 1);
  CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
  CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
  CGContextStrokePath(context);
};
[self.view addSubview:drawableView];

6

आप रेखाओं को खींचने के लिए UIImageView का उपयोग कर सकते हैं।

हालाँकि, यह सब-क्लासिंग को छोड़ देता है। और जैसा कि मैं कोर ग्राफिक्स के लिए थोड़ा इच्छुक हूं अभी भी इसका उपयोग कर सकता हूं। आप इसे बस में डाल सकते हैं -ViewDidLoad

  UIGraphicsBeginImageContext(self.view.frame.size);
  [self.myImageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
  CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
  CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);

  CGContextMoveToPoint(UIGraphicsGetCurrentContext(), 50, 50);
  CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), 200, 200);
  CGContextStrokePath(UIGraphicsGetCurrentContext());
  CGContextFlush(UIGraphicsGetCurrentContext());
  self.myImageView.image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

रोब के जवाब के अलावा, एक तड़के के लिए, तीसरा दृष्टिकोण एक का उपयोग करना है UIImageView- इसके साथ कवर - xib का दृश्य। (Xcode 5 में xib पर घसीटे जाने पर डिफ़ॉल्ट UIImageView उपस्थिति)

चीयर्स और +1!


2

आपको वास्तव में नहीं होना चाहिए, लेकिन अगर किसी कारण से यह आपके लिए समझ में आता है, तो आप एक उपवर्ग बना सकते हैं, DelegateDrawViewउदाहरण के लिए, यह एक प्रतिनिधि लेता है जो एक विधि को लागू करता है जैसे

- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect

और फिर विधियों में - [DelegateDrawView drawRect:]आपको अपनी प्रतिनिधि पद्धति को कॉल करना चाहिए।

लेकिन आप अपने कंट्रोलर में व्यू कोड क्यों डालना चाहेंगे।

आप UIView का एक उपवर्ग बनाने से बेहतर हैं, जो इसके दो कोनों के बीच एक रेखा खींचता है, आपके पास यह सेट करने के लिए एक संपत्ति हो सकती है कि कौन सी दो और फिर उस स्थिति को देखें जहां से आप इसे चाहते हैं।


1

आपके विचार के अंदर आकर्षित करने के लिए बहुत आसान है, @ Mr.ROB ने कहा कि 2 विधि मैंने पहली विधि ली।

बस उस कोड को कॉपी करें जहाँ आप लोग चाहते हैं।

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
     startingPoint = [touch locationInView:self.view];

    NSLog(@"Touch starting point = x : %f Touch Starting Point = y : %f", touchPoint.x, touchPoint.y);
}
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
     touchPoint = [touch locationInView:self.view];

    NSLog(@"Touch end point =x : %f Touch end point =y : %f", touchPoint.x, touchPoint.y);
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [[event allTouches] anyObject];
    touchPoint = [touch locationInView:self.view];
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
    [path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)];
    startingPoint=touchPoint;
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [path CGPath];
    shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
    shapeLayer.lineWidth = 3.0;
    shapeLayer.fillColor = [[UIColor redColor] CGColor];
    [self.view.layer addSublayer:shapeLayer];

    NSLog(@"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);
    [self.view setNeedsDisplay];


}
- (void)tapGestureRecognizer:(UIGestureRecognizer *)recognizer {
    CGPoint tappedPoint = [recognizer locationInView:self.view];
    CGFloat xCoordinate = tappedPoint.x;
    CGFloat yCoordinate = tappedPoint.y;

    NSLog(@"Touch Using UITapGestureRecognizer x : %f y : %f", xCoordinate, yCoordinate);
}

यह एक रेखा की तरह खींचेगा, जहां उंगली जा रही है

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