在 UIView 中画线

我需要在 UIView 中画一条水平线。最简单的方法是什么。例如,我想在 y-coord = 200处绘制一条黑色水平线。

我没有用 Interface Builder。

152639 次浏览

The easiest way in your case (horizontal line) is to add a subview with black background color and frame [0, 200, 320, 1].

Code sample (I hope there are no errors - I wrote it without Xcode):

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

Another way is to create a class that will draw a line in its drawRect method (you can see my code sample for this here).

Maybe this is a bit late, but I want to add that there is a better way. Using UIView is simple, but relatively slow. This method overrides how the view draws itself and is faster:

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

Just add a Label without text and with background color. Set the Coordinates of your choice and also height and width. You can do it manually or with Interface Builder.

You can user UIBezierPath Class for this:

And can draw as many lines as you want:

I have subclassed UIView :

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


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

And initialized the pathArray and dictPAth objects which will be used for line drawing. I am writing the main portion of the code from my own project:

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


}

touchesBegin method :

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

touchesMoved Method:

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];

touchesEnded Method:

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

One other (and an even shorter) possibility. If you're inside drawRect, something like the following:

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

Swift 3 and Swift 4

This is how you can draw a gray line at the end of your view (same idea as b123400's answer)

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

Based on Guy Daher's answer.

I try to avoid using ? because it can cause an application crash if the GetCurrentContext() returns nil.

I would do nil check if statement:

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

Add label without text and with background color corresponding frame size(ex:height=1). Do it through code or in interface builder.

Swift 3, 4, 5

This is the simplest of all I could find...

let lineView = UIView(frame: CGRect(x: 4, y: 50, width: self.view.frame.width, height: 1))
lineView.backgroundColor = .lightGray
self.view.addSubview(lineView)