2011-05-31 15 views
2

我试图建立一些iOS应用程序,同时学习,并有一些麻烦理解正确的方法来做到这一点。如何使用drawRect更新我的自定义UIView?

我目前有一个视图是UIView的子类。很明显,我想用它作为绘图表面。它会坐在别的东西之上,如描图纸。

用户应该能够点击一个点然后另一个点和一条线应该在2点之间画。我得到触摸数据,我有点,我可以从drawRect内部画东西:最初。

问题是我不知道以后如何更新内容。当一切都加载和drawRect:是calle,它会画一条线就好了。但是,如何根据用户正在做什么来绘制新东西或更改已绘制的东西。我知道我需要调用setNeedsDisplay,但不知道如何获取数据到视图来绘制东西。

我读过一堆教程/例子,他们都停在“覆盖drawRect:并画出一些东西......完成!”。如何将数据传递给视图以告诉它“嘿,重绘这些东西并添加这个新行”。

或者,我是否在谈论这一切错误的方式?

编辑: 我会尽力解释我的设置。

我有一个VC。在VC的视图中,我在底部有一个工具栏。该地区的其余部分被2个景观占用。一个是保存参考图像的图像视图。一个是自定义视图,清晰(描图纸),位于顶部。他们点击工具栏上的一个按钮,打开一个gesturerecognizer。他们点击屏幕,我收集点击数据,关闭gesturerecognizer和HOPEFULLY画一条线。除了绘图部分,我已经完成了所有工作。

+2

你说你 “之分”。你如何储存它们? – 2011-05-31 21:51:48

+0

CGPoints包含每个“行”的开始和停止的坐标位置。现在他们正在被风险投资持有。 – 2011-05-31 22:04:08

回答

4

你是在正确的轨道上。听起来像你需要跟踪点。

下面是一些示例代码。

LineDrawView.h

#import <UIKit/UIKit.h> 
@interface LineDrawView : UIView 
{ 
    NSMutableArray *lines; 
    CGPoint pointA, pointB; 
    BOOL activeLine; 
} 
@end 

LineDrawView.m

#import "LineDrawView.h" 
@implementation LineDrawView 
- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) 
    { 
     self.backgroundColor = [UIColor blackColor]; 
     lines = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 
- (void)dealloc 
{ 
    [lines release]; 
    [super dealloc]; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 
    CGPoint point = [[touches anyObject] locationInView:self]; 
    if ([lines count] == 0) pointA = point; 
    else pointB = point; 
    activeLine = YES; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesMoved:touches withEvent:event]; 
    pointB = [[touches anyObject] locationInView:self]; 
    [self setNeedsDisplay]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesEnded:touches withEvent:event]; 
    pointB = [[touches anyObject] locationInView:self]; 
    [lines addObject:[NSArray arrayWithObjects:[NSValue valueWithCGPoint:pointA], [NSValue valueWithCGPoint:pointB], nil]]; 
    pointA = pointB; 
    pointB = CGPointZero; 
    activeLine = NO; 
    [self setNeedsDisplay]; 
} 

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef c = UIGraphicsGetCurrentContext(); 
    CGContextSetLineWidth(c, 2); 
    CGContextSetLineCap(c, kCGLineCapRound); 
    CGContextSetLineJoin(c, kCGLineJoinRound); 
    CGContextSetStrokeColorWithColor(c, [UIColor grayColor].CGColor); 
    for (NSArray *line in lines) 
    { 
     CGPoint points[2] = { [[line objectAtIndex:0] CGPointValue], [[line objectAtIndex:1] CGPointValue] }; 
     CGContextAddLines(c, points, 2); 
    } 
    CGContextStrokePath(c); 
    if (activeLine) 
    { 
     CGContextSetStrokeColorWithColor(c, [UIColor whiteColor].CGColor); 
     CGPoint points2[2] = { pointA, pointB }; 
     CGContextAddLines(c, points2, 2); 
     CGContextStrokePath(c); 
    } 
} 
@end 
+0

我读了touchesBegan等。他们似乎不是我想要的。我编辑了我的问题,试图阐述我在做什么。我正在使用一个VC,并且VC打开/关闭了一个手势识别器,用于处理用户正在做什么。我收集的要点很好,并存储他们罚款。我只是不知道如何将这些数据传递给视图来完成绘图。 纠正我,如果我错了,但你的解决方案似乎完全依赖于自定义UIView。我希望它在自定义UIView是愚蠢的地方工作。并且只根据我从VC传递给它的数据绘制线条。 我对这种做法有错吗? – 2011-05-31 22:24:56

+1

不,你没有错,你的方法应该正常工作。你应该能够忽略'touches'方法并直接从不同的类中填充'line'数组。只要你在更新数组后立即调用'setNeedsDisplay',点和线的填充就没有关系。 – tidwall 2011-05-31 23:11:54

+0

哦..我是个白痴。我只需要在VC中设置一些自定义视图变量,然后调用setNeedsDisplay不是吗? – 2011-05-31 23:36:51

相关问题