Vẽ đường trong UIView


86

Tôi cần vẽ một đường ngang trong UIView. Cách dễ nhất để làm điều đó là gì. Ví dụ, tôi muốn vẽ một đường ngang màu đen tại y-coord = 200.

Tôi KHÔNG sử dụng Trình tạo giao diện.


1
Đây là giải pháp hoàn chỉnh và dễ dàng để có đúng một dòng duy nhất-pixel, trong tất cả iOS, và làm cho nó dễ dàng trong kịch bản: stackoverflow.com/a/26525466/294884
Fattie

Câu trả lời:


122

Cách dễ nhất trong trường hợp của bạn (đường ngang) là thêm một chế độ xem phụ với màu nền và khung màu đen [0, 200, 320, 1].

Mẫu mã (Tôi hy vọng không có lỗi - Tôi đã viết nó mà không có 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...

Một cách khác là tạo một lớp sẽ vẽ một đường trong phương thức drawRect của nó (bạn có thể xem mẫu mã của tôi cho điều này tại đây ).


Làm điều này mà không cần bất kỳ mã nào trong Storyboard. Nó dễ dàng hơn và tốt hơn.
coolcool1994

3
@ coolcool1994, bạn có nhận thấy "Tôi KHÔNG sử dụng Trình tạo giao diện." yêu cầu trong câu hỏi?
Michael Kessler

312

Có thể điều này là hơi muộn, nhưng tôi muốn nói thêm rằng có một cách tốt hơn. Sử dụng UIView rất đơn giản, nhưng tương đối chậm. Phương thức này ghi đè cách chế độ xem tự vẽ và nhanh hơn:

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

Nếu mã này được sử dụng trong UIView thì các tọa độ trong mẫu này có liên quan đến giới hạn của chế độ xem hoặc toàn bộ màn hình không?
ChrisP

Có ai không cần phải gọi CGContextBeginPath(context);trước CGContextMoveToPoint(...);?
i_am_jorf

37
Sử dụng một lượt xem để làm điều đó không quá kinh khủng. Nó làm cho mọi thứ dễ dàng hơn, chẳng hạn như khi thực hiện các hoạt ảnh ngầm trong quá trình thay đổi hướng. Nếu nó chỉ là một, UIView khác không phải là tất cả đắt tiền và mã đơn giản hơn nhiều.
i_am_jorf

Ngoài ra, bạn có thể nhận được giới hạn và điểm giữa với các mã này: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994 ngày

1
Đúng, nhận xét rằng nó là "chậm" là không hợp lý. Có rất nhiều UIViews đơn giản trên màn hình bất cứ lúc nào. Lưu ý rằng việc vẽ MỘT (!) Ký tự văn bản, với tất cả quá trình xử lý liên quan, đầm lầy sẽ vẽ một UIView đầy đủ.
Fattie

30

Swift 3 và Swift 4

Đây là cách bạn có thể vẽ một đường màu xám ở cuối chế độ xem của mình (cùng ý tưởng với câu trả lời của 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()
        }
    }
}

"If let context" không thành công khi được gọi từ viewDidLayoutSubviews.
Oscar

14

Chỉ cần thêm Nhãn không có văn bản và có màu nền. Đặt Tọa độ bạn chọn cũng như chiều cao và chiều rộng. Bạn có thể làm điều đó theo cách thủ công hoặc với Trình tạo giao diện.


11

Bạn có thể sử dụng Lớp UIBezierPath cho việc này:

Và có thể vẽ bao nhiêu đường tùy thích:

Tôi đã phân loại UIView:

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

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

Và khởi tạo các đối tượng pathArray và dictPAth sẽ được sử dụng để vẽ đường. Tôi đang viết phần chính của mã từ dự án của riêng tôi:

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

}

Phương thức touchBegin:

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

Phương pháp chạm

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

phương pháp chạm

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

11

Một khả năng khác (và thậm chí còn ngắn hơn). Nếu bạn đang ở trong drawRect, một cái gì đó giống như sau:

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

0

Dựa trên câu trả lời của Guy Daher.

Tôi cố gắng tránh sử dụng? vì nó có thể gây ra lỗi ứng dụng nếu GetCurrentContext () trả về nil.

Tôi sẽ không kiểm tra câu lệnh if:

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
nếu lý do cho ifmệnh đề chỉ là để bỏ hộp khỏi tùy chọn, hãy sử dụng một guardcâu lệnh thay thế.
Julio Flores

-1

Thêm nhãn không có văn bản và với kích thước khung tương ứng với màu nền (ví dụ: chiều cao = 1). Làm điều đó thông qua mã hoặc trong trình tạo giao diện.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.