ลากเส้นใน UIView


86

ฉันต้องการวาดเส้นแนวนอนใน UIView วิธีที่ง่ายที่สุดที่จะทำคืออะไร ตัวอย่างเช่นฉันต้องการวาดเส้นแนวนอนสีดำที่ y-Coord = 200

ฉันไม่ได้ใช้ Interface Builder


1
นี่คือวิธีแก้ปัญหาที่ง่ายและสมบูรณ์ในการมีเส้นพิกเซลเดียวอย่างถูกต้องใน iOS ทั้งหมดและทำให้ง่ายในสตอรีบอร์ด: stackoverflow.com/a/26525466/294884
Fattie

คำตอบ:


122

วิธีที่ง่ายที่สุดในกรณี (เส้นแนวนอน) ของคุณคือการเพิ่ม subview [0, 200, 320, 1]กับสีพื้นหลังสีดำและกรอบ

ตัวอย่างโค้ด (ฉันหวังว่าจะไม่มีข้อผิดพลาด - ฉันเขียนโดยไม่มี 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...

อีกวิธีหนึ่งคือการสร้างคลาสที่จะลากเส้นในเมธอด drawRect (คุณสามารถดูตัวอย่างโค้ดของฉันได้ที่นี่ )


ทำได้โดยไม่ต้องใช้รหัสใด ๆ ใน Storyboard ง่ายและดีกว่า
coolcool1994

3
@ coolcool1994 คุณไม่สังเกตเห็น "ฉันไม่ได้ใช้ตัวสร้างส่วนต่อประสาน" ความต้องการในคำถาม?
Michael Kessler

312

อาจจะช้าไปหน่อย แต่ฉันต้องการเพิ่มว่ามีวิธีที่ดีกว่านี้ การใช้ UIView นั้นง่าย แต่ค่อนข้างช้า วิธีนี้จะลบล้างวิธีที่มุมมองดึงตัวเองและเร็วขึ้น:

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

หากใช้รหัสนี้ใน UIView พิกัดในตัวอย่างนี้สัมพันธ์กับขอบเขตของมุมมองหรือทั้งหน้าจอหรือไม่
ChrisP

ใครไม่ต้องโทรCGContextBeginPath(context);มาก่อนCGContextMoveToPoint(...);?
i_am_jorf

37
ใช้มุมมองในการทำมันไม่ได้น่ากลัวเกินไป ทำให้สิ่งต่างๆง่ายขึ้นตัวอย่างเช่นเมื่อทำภาพเคลื่อนไหวโดยนัยในระหว่างการเปลี่ยนแปลงการวางแนว หากเป็นเพียงอันเดียว UIView อื่นก็ไม่ได้มีราคาแพงและรหัสนั้นง่ายกว่ามาก
i_am_jorf

นอกจากนี้คุณสามารถกำหนดขอบเขตและจุดกึ่งกลางด้วยรหัสเหล่านี้: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994

1
ถูกต้องความคิดเห็นที่ว่า "ช้า" นั้นไม่สมเหตุสมผล มี UIViews จำนวนมากบนหน้าจอได้ตลอดเวลา โปรดทราบว่าการวาดอักขระข้อความ ONE (!) ด้วยการประมวลผลทั้งหมดที่เกี่ยวข้องหนองน้ำจะวาด UIView ที่เต็มไป
Fattie

30

Swift 3 และ Swift 4

นี่คือวิธีวาดเส้นสีเทาที่ส่วนท้ายของมุมมองของคุณ (แนวคิดเดียวกับคำตอบของ 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" ล้มเหลวเมื่อเรียกจาก viewDidLayoutSubviews
ออสกา

14

เพียงเพิ่มป้ายกำกับที่ไม่มีข้อความและสีพื้นหลัง กำหนดพิกัดที่คุณต้องการรวมทั้งความสูงและความกว้าง คุณสามารถทำได้ด้วยตนเองหรือด้วย Interface Builder


11

คุณสามารถใช้ UIBezierPath Class สำหรับสิ่งนี้:

และสามารถลากเส้นได้มากเท่าที่คุณต้องการ:

ฉันมี UIView subclassed:

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

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

และเริ่มต้นวัตถุ pathArray และ dictPAth ซึ่งจะใช้สำหรับการวาดเส้น ฉันกำลังเขียนส่วนหลักของโค้ดจากโครงการของฉันเอง:

- (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:

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

วิธีการสัมผัส

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 วิธีการ:

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

11

ความเป็นไปได้อีกอย่างหนึ่ง (และสั้นกว่านั้น) หากคุณอยู่ใน drawRect สิ่งต่อไปนี้:

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

0

จากคำตอบของ Guy Daher

ฉันพยายามหลีกเลี่ยงการใช้? เนื่องจากอาจทำให้แอปพลิเคชันหยุดทำงานได้หาก GetCurrentContext () ส่งกลับค่า nil

ฉันจะตรวจสอบว่าคำสั่ง:

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
หากเหตุผลของifประโยคเป็นเพียงการ unbox จากทางเลือกให้เลือกใช้guardคำสั่งแทน
Julio Flores

-1

เพิ่มป้ายกำกับโดยไม่มีข้อความและมีสีพื้นหลังขนาดเฟรมที่สอดคล้องกัน (เช่นความสูง = 1) ทำผ่านรหัสหรือในตัวสร้างอินเทอร์เฟซ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.