Нарисуйте 5-пиксельную линию в UIView

У меня очень простой (надеюсь очень простой) вопрос. Как в Objective-C нарисовать линию между двумя точками и добавить ее в UIView? Я пытался использовать UIImageView и манипулировать его свойством Transform, но в итоге линия превратилась в квадрат или прямоугольник при использовании следующего кода:

[[self tline] setFrame:CGRectMake(start.x, start.y, width, 5)];
[[self tline] setTransform:CGAffineTransformMakeRotation(angle)];

У меня есть две CGPoints, start и end, и я хотел бы нарисовать динамическую линию 5px между двумя точками и добавить ее в свое подпредставление.

БК:

Точка start — это точка, в которой пользователь начинает касаться экрана, а точка end — это точка, в которой в данный момент находится палец пользователя. Очевидно, что это будет много двигаться во время игры. Мне нужно иметь возможность перемещать эту линию, чтобы соединить эти две точки.

Я использую методы touchesBegan:, Moved:, and Ended: для создания, перемещения и уничтожения линии.

CoreGraphics

У меня есть следующий код; как добавить эту строку в self.view?

CGContextRef c = UIGraphicsGetCurrentContext();
CGFloat color[4] = {1.0f, 1.0f, 1.0f, 0.6f};
CGContextSetStrokeColor(c, color);
CGContextBeginPath(c);
CGContextMoveToPoint(c, start.x, start.y);
CGContextAddLineToPoint(c, end.x, end.y);
CGContextSetLineWidth(c, 5);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextStrokePath(c);

Пользовательский интерфейс:

#import <UIKit/UIKit.h>

@interface DrawingView : UIView

@property (nonatomic) CGPoint start;
@property (nonatomic) CGPoint end;

- (void)drawRect:(CGRect)rect;

@end

#import "DrawingView.h"

@implementation DrawingView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextSetLineCap(context, kCGLineCapSquare);
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); //change color here
    CGFloat lineWidth = 5.0; //change line width here
    CGContextSetLineWidth(context, lineWidth);
    CGPoint startPoint = [self start];
    CGPoint endPoint = [self end];
    CGContextMoveToPoint(context, startPoint.x + lineWidth/2, startPoint.y + lineWidth/2);
    CGContextAddLineToPoint(context, endPoint.x + lineWidth/2, endPoint.y + lineWidth/2);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);

    NSLog(@"%f",_end.x);
}

- (void)setEnd:(CGPoint)end
{
    _end = end;
    [self setNeedsDisplay];
}

@end

drawRect: вызывается только при инициализации представления...

Метод рисования в UIViewController:

- (void)drawTLine:(CGPoint)start withEndPoint:(CGPoint)end
{   
    [[self dview] setStart:start];
    [[self dview] setEnd:end];
    [[self dview] drawRect:[self dview].frame];
}

Вот как я добавляю чертежный вид:

DrawingView* dview = [[DrawingView alloc] initWithFrame:self.view.frame];
[dview setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:dview];

person David    schedule 27.03.2013    source источник
comment
Рассматривали ли вы Core Graphics, используя метод draw: UIView?   -  person anon_dev1234    schedule 28.03.2013
comment
Если я использую метод рисования, как я буду отслеживать линию? Мне нужно иметь возможность перемещать его, изменять его размер и уничтожать по мере необходимости.   -  person David    schedule 28.03.2013
comment
Что ж, в вашем перемещенном событии вы, возможно, можете обновить свойство/переменную, чтобы отслеживать текущую позицию. Метод draw: вызывается при каждом обновлении, поэтому вы просто рисуете точку между начальной и текущей и стираете все старые линии. Очистка довольно проста, как описано здесь - › stackoverflow.com/a/7907669/1415949   -  person anon_dev1234    schedule 28.03.2013
comment
Ответ Габриэле должен работать хорошо, пока вы рисуете прямые линии.   -  person anon_dev1234    schedule 28.03.2013
comment
Две вещи; как реализовать это в представлении UIViewController и как мне вызвать этот метод? Мне нужно дать ему два CGPoints, чтобы провести линию между ними.   -  person David    schedule 28.03.2013
comment
Создайте собственное представление — установите его в качестве представления вашего контроллера представления в viewDidLoad:. Затем в своем пользовательском представлении реализуйте метод drawRect: — после его реализации он автоматически вызывается при каждом прогоне цикла событий. Я бы посоветовал прочитать UIView и CoreGraphics в документации Apple.   -  person anon_dev1234    schedule 28.03.2013
comment
См. stackoverflow.com/questions/5847876/   -  person Nikolai Ruhe    schedule 28.03.2013
comment
@NikolaiRuhe Это сработало отлично! Все, что мне нужно было сделать, это отключить неявную анимацию. Отличное объяснение! Спасибо! Переместите его к ответу, и я дам вам точку ответа!   -  person David    schedule 28.03.2013
comment
Это нормально. Вы можете проголосовать за связанный ответ, если хотите.   -  person Nikolai Ruhe    schedule 28.03.2013


Ответы (2)


Подкласс UIView и выполнение пользовательского рисования с использованием метода drawRect:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextSetLineCap(context, kCGLineCapSquare);
    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor); //change color here
    CGFloat lineWidth = 1.0; //change line width here
    CGContextSetLineWidth(context, lineWidth); 
    CGPoint startPoint = rect.origin; //change start point here
    CGPoint endPoint = {.x = CGRectGetMaxX(rect), .y = startPoint.y} //change end point here
    CGContextMoveToPoint(context, startPoint.x + lineWidth/2, startPoint.y + lineWidth/2);
    CGContextAddLineToPoint(context, endPoint.x + lineWidth/2, endPoint.y + lineWidth/2);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);        
}

Это нарисует черную линию толщиной 1 пиксель в верхней части вашего UIView.

Если вам нужно обновить строку, вы можете просто использовать некоторые свойства, такие как

@property (nonatomic) CGPoint startPoint;

и предоставить пользовательскую реализацию для установщика, например

- (void)setStartPoint:(CGPoint)point {
      _point = point;
      [self setNeedsDisplay]; // this will cause drawRect: to be called again
}

Сделайте это для каждого свойства, которым вы хотите управлять, и заставьте drawRect: использовать эти свойства для рисования.

person Gabriele Petronella    schedule 27.03.2013
comment
Я знаю, но это не повредит и сделает все аккуратнее, если после этого вы выполняете другие пользовательские рисунки ;) - person Gabriele Petronella; 28.03.2013
comment
Хорошо, я добавил это как пользовательский UIView и реализовал метод для установки конечной точки (вместо начальной точки), но drawRect: не вызывается после добавления представления. - person David; 28.03.2013
comment
Как вы добавляете представление? - person Gabriele Petronella; 28.03.2013
comment
Пожалуйста, проверьте редактирование. - person David; 28.03.2013
comment
Вы делаете несколько вещей неправильно. Вам не нужно объявлять - (void)drawRect:(CGRect)rect; сверху, так как это существующий метод UIView. Более того, вам не нужно вручную вызывать drawRect:. Он вызывается всякий раз, когда изменяется кадр представления, например. при инициализации с помощью initWithFrame: - person Gabriele Petronella; 28.03.2013

вы можете создать и UIBezierPath вот так

UIBezierPath path = [[UIBezierPath alloc] init]
[path moveToPoint: CGPoint(x,y)] // X and Y, start point
[path addLineToPoint:CGPoint(x2,y2) // X2 and Y2, end point

если вы хотите создать фигуру, вы можете поставить больше точек с помощью метода addLineToPoint: и закончить, используя метод closePath

Я надеюсь помочь вам

person kakashy    schedule 27.03.2013