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.

John Smith
quelle
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 ).

Michael Kessler
quelle
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);
}
b123400
quelle
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()
        }
    }
}
Guy Daher
quelle
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.

Phanindra
quelle
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];
Rakesh
quelle
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});
hkatz
quelle
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()
        }
    }
}
Robert Harrold
quelle
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.

Reddy
quelle