Zeichnen Sie eine Linie in UIView


86

Ich muss in einer UIView eine horizontale Linie zeichnen. Was ist der einfachste Weg, es zu tun. Zum Beispiel möchte ich eine schwarze horizontale Linie bei y-Koordinate = 200 zeichnen.

Ich benutze NICHT Interface Builder.


1
Hier ist die vollständige und einfache Lösung, um eine Single-Pixel-Zeile in allen iOS- Versionen
Fattie

Antworten:


121

In Ihrem Fall (horizontale Linie) ist es am einfachsten, eine Unteransicht mit schwarzer Hintergrundfarbe und schwarzem Rahmen hinzuzufügen [0, 200, 320, 1].

Codebeispiel (Ich hoffe, es gibt keine Fehler - ich habe es ohne Xcode geschrieben):

UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];
[lineView release];
// You might also keep a reference to this view 
// if you are about to change its coordinates.
// Just create a member and a property for this...

Eine andere Möglichkeit besteht darin, eine Klasse zu erstellen, die in ihrer drawRect-Methode eine Linie zeichnet (mein Codebeispiel hierfür finden Sie hier ).


Tun Sie dies ohne Code in Storyboard. Es ist einfacher und besser.
coolcool1994

2
@ coolcool1994, hast du nicht bemerkt "Ich verwende NICHT Interface Builder." Anforderung in der Frage?
Michael Kessler

311

Vielleicht ist das etwas spät, aber ich möchte hinzufügen, dass es einen besseren Weg gibt. Die Verwendung von UIView ist einfach, aber relativ langsam. Diese Methode überschreibt, wie sich die Ansicht selbst zeichnet und ist schneller:

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);

    // Draw them with a 2.0 stroke width so they are a bit more visible.
    CGContextSetLineWidth(context, 2.0f);

    CGContextMoveToPoint(context, 0.0f, 0.0f); //start at this point

    CGContextAddLineToPoint(context, 20.0f, 20.0f); //draw to this point

    // and now draw the Path!
    CGContextStrokePath(context);
}

Wenn dieser Code in einer UIView verwendet wird, sind die Koordinaten in diesem Beispiel relativ zu den Grenzen der Ansicht oder des gesamten Bildschirms?
ChrisP

Muss man CGContextBeginPath(context);vorher nicht anrufen CGContextMoveToPoint(...);?
i_am_jorf

37
Es ist nicht allzu schrecklich, eine Ansicht zu verwenden. Dies erleichtert beispielsweise die Ausführung impliziter Animationen bei Orientierungsänderungen. Wenn es nur eines ist, ist ein anderes UIView nicht allzu teuer und der Code ist viel einfacher.
i_am_jorf

Darüber hinaus können Sie mit diesen Codes Grenzen und Mittelpunkt ermitteln: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994

1
Richtig, der Kommentar, dass es "langsam" ist, ist nicht sinnvoll. Es gibt jederzeit eine große Anzahl einfacher UIViews auf dem Bildschirm. Beachten Sie, dass das Zeichnen eines (!) Textzeichens bei der gesamten Verarbeitung das Zeichnen einer gefüllten UIView überflutet.
Fattie

29

Swift 3 und Swift 4

So können Sie am Ende Ihrer Ansicht eine graue Linie zeichnen (dieselbe Idee wie die Antwort von b123400).

class CustomView: UIView {

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        if let context = UIGraphicsGetCurrentContext() {
            context.setStrokeColor(UIColor.gray.cgColor)
            context.setLineWidth(1)
            context.move(to: CGPoint(x: 0, y: bounds.height))
            context.addLine(to: CGPoint(x: bounds.width, y: bounds.height))
            context.strokePath()
        }
    }
}

Der "if let context" schlägt fehl, wenn er von viewDidLayoutSubviews aufgerufen wird.
Oscar

14

Fügen Sie einfach ein Etikett ohne Text und mit Hintergrundfarbe hinzu. Stellen Sie die Koordinaten Ihrer Wahl sowie Höhe und Breite ein. Sie können dies manuell oder mit Interface Builder tun.


11

Sie können die UIBezierPath-Klasse dafür verwenden:

Und kann so viele Linien zeichnen, wie Sie möchten:

Ich habe UIView untergeordnet:

    @interface MyLineDrawingView()
    {
       NSMutableArray *pathArray;
       NSMutableDictionary *dict_path;
       CGPoint startPoint, endPoint;
    }

       @property (nonatomic,retain)   UIBezierPath *myPath;
    @end

Und initialisiert die pathArray- und dictPAth-Objekte, die für das Strichzeichnen verwendet werden. Ich schreibe den Hauptteil des Codes aus meinem eigenen Projekt:

- (void)drawRect:(CGRect)rect
{

    for(NSDictionary *_pathDict in pathArray)
    {
        [((UIColor *)[_pathDict valueForKey:@"color"]) setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)
        [[_pathDict valueForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    }

    [[dict_path objectForKey:@"color"] setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)
    [[dict_path objectForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];

}

touchBegin-Methode:

UITouch *touch = [touches anyObject];
startPoint = [touch locationInView:self];
myPath=[[UIBezierPath alloc]init];
myPath.lineWidth = currentSliderValue*2;
dict_path = [[NSMutableDictionary alloc] init];

touchMoved-Methode:

UITouch *touch = [touches anyObject];
endPoint = [touch locationInView:self];

 [myPath removeAllPoints];
        [dict_path removeAllObjects];// remove prev object in dict (this dict is used for current drawing, All past drawings are managed by pathArry)

    // actual drawing
    [myPath moveToPoint:startPoint];
    [myPath addLineToPoint:endPoint];

    [dict_path setValue:myPath forKey:@"path"];
    [dict_path setValue:strokeColor forKey:@"color"];

    //                NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path];
    //                [pathArray addObject:tempDict];
    //                [dict_path removeAllObjects];
    [self setNeedsDisplay];

touchEnded Methode:

        NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path];
        [pathArray addObject:tempDict];
        [dict_path removeAllObjects];
        [self setNeedsDisplay];

11

Eine andere (und noch kürzere) Möglichkeit. Wenn Sie sich in drawRect befinden, gehen Sie wie folgt vor:

[[UIColor blackColor] setFill];
UIRectFill((CGRect){0,200,rect.size.width,1});

0

Basierend auf der Antwort von Guy Daher.

Ich versuche zu vermeiden, zu verwenden? weil es einen Anwendungsabsturz verursachen kann, wenn GetCurrentContext () nil zurückgibt.

Ich würde keine if-Anweisung überprüfen:

class CustomView: UIView 
{    
    override func draw(_ rect: CGRect) 
    {
        super.draw(rect)
        if let context = UIGraphicsGetCurrentContext()
        {
            context.setStrokeColor(UIColor.gray.cgColor)
            context.setLineWidth(1)
            context.move(to: CGPoint(x: 0, y: bounds.height))
            context.addLine(to: CGPoint(x: bounds.width, y: bounds.height))
            context.strokePath()
        }
    }
}

2
Wenn der Grund für die ifKlausel nur darin besteht, die Option zu deaktivieren, verwenden Sie guardstattdessen lieber eine Anweisung.
Julio Flores

-1

Fügen Sie eine Beschriftung ohne Text und mit der entsprechenden Rahmengröße für die Hintergrundfarbe hinzu (Beispiel: Höhe = 1). Tun Sie es durch Code oder im Interface Builder.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.