Накресліть лінію в UIView


86

Мені потрібно намалювати горизонтальну лінію в UIView. Який найпростіший спосіб це зробити. Наприклад, я хочу намалювати чорну горизонтальну лінію з координатою y = 200.

Я НЕ використовую Interface Builder.


1
Ось повне та просте рішення, як правильно мати лінію з одним пікселем у всіх iOS та полегшити його в розкадровці: stackoverflow.com/a/26525466/294884
Fattie,

Відповіді:


122

Найпростіший спосіб у вашому випадку (горизонтальна лінія) - це додати підпрогляд із чорним кольором тла та рамкою [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, ви не помітили "Я НЕ використовую Interface Builder". вимога у питанні?
Майкл Кесслер

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 02

Крім того, ви можете отримати межі та середню точку за допомогою таких кодів: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994 03.03.13

1
Правильно, коментар про те, що він "повільний", не є розумним. На екрані в будь-який час є величезна кількість простих UIViews. Зверніть увагу, що малювання ОДНОГО (!) Текстового символу, з усією обробкою, яка включає, болота, малювання заповненого UIView.
Fattie

30

Свіфт 3 і Свіфт 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()
        }
    }
}

"Якщо дозволити контексту" не вдається при виклику з viewDidLayoutSubviews.
Оскар

14

Просто додайте ярлик без тексту та з кольором тла. Встановіть вибрані вами координати, а також висоту та ширину. Ви можете зробити це вручну або за допомогою Interface Builder.


11

Ви можете користуватися класом UIBezierPath для цього:

І можете намалювати скільки завгодно ліній:

Я підклас UIView:

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

}

Метод touchesBegin:

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

Метод закінчення:

        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

На основі відповіді Гая Дахера.

Я намагаюся уникати використання? тому що це може спричинити збій програми, якщо 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пункту є просто розпакування з необов’язкового, guardзамість цього скористайтеся оператором.
Хуліо Флорес

-1

Додайте мітку без тексту та з кольором фону, що відповідає розміру кадру (наприклад: висота = 1). Зробіть це за допомогою коду або в конструкторі інтерфейсу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.