Мне нужно нарисовать горизонтальную линию в UIView. Как это сделать проще всего. Например, я хочу нарисовать черную горизонтальную линию с координатой y = 200.
Вот полное и простое решение для правильного создания однопиксельной линии во всех 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 (вы можете увидеть мой пример кода для этого здесь ).
Сделайте это без кода в раскадровке. Так проще и лучше.
coolcool1994 06
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 pointCGContextAddLineToPoint(context, 20.0f, 20.0f); //draw to this point// and now draw the Path!CGContextStrokePath(context);
}
Если этот код используется в UIView, будут ли координаты в этом примере относительно границ представления или всего экрана?
ChrisP
Есть ли один не нужно позвонить , CGContextBeginPath(context);прежде чем CGContextMoveToPoint(...);?
i_am_jorf 09
37
Использование представления для этого не так уж и ужасно. Это упрощает работу, например, при выполнении неявной анимации во время изменения ориентации. Если это всего лишь один, другой UIView не так уж и дорог, а код намного проще.
i_am_jorf 02
Кроме того, вы можете получить границы и среднюю точку с помощью этих кодов: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994
1
Да, комментарий о том, что он "медленный", не имеет смысла. На экране в любое время появляется огромное количество простых UIView. Обратите внимание, что рисование ОДНОГО (!) Текстового символа со всей необходимой обработкой заменяет рисование заполненного UIView.
Fattie
30
Swift 3 и Swift 4
Вот как вы можете нарисовать серую линию в конце вашего представления (та же идея, что и ответ b123400)
«Если разрешить контекст» не работает при вызове из viewDidLayoutSubviews.
Оскар
14
Просто добавьте метку без текста и с цветом фона. Установите координаты по вашему выбору, а также высоту и ширину. Вы можете сделать это вручную или с помощью Interface Builder.
И инициализировал объекты 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:kCGBlendModeNormalalpha: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:kCGBlendModeNormalalpha:1.0];
}
Ответы:
Самый простой способ в вашем случае (горизонтальная линия) - добавить подпредставление с черным цветом фона и рамкой
[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 (вы можете увидеть мой пример кода для этого здесь ).
источник
Возможно, это немного поздно, но я хочу добавить, что есть способ получше. Использовать 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); }
источник
CGContextBeginPath(context);
прежде чемCGContextMoveToPoint(...);
?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() } } }
источник
Просто добавьте метку без текста и с цветом фона. Установите координаты по вашему выбору, а также высоту и ширину. Вы можете сделать это вручную или с помощью Interface Builder.
источник
Вы можете использовать класс 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];
touchMoved Метод:
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];
touchesEnded Метод:
NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path]; [pathArray addObject:tempDict]; [dict_path removeAllObjects]; [self setNeedsDisplay];
источник
Еще одна (и даже более короткая) возможность. Если вы находитесь внутри drawRect, что-то вроде следующего:
[[UIColor blackColor] setFill]; UIRectFill((CGRect){0,200,rect.size.width,1});
источник
На основе ответа Гая Дахера.
Я стараюсь избегать использования? потому что это может вызвать сбой приложения, если GetCurrentContext () вернет ноль.
Я бы сделал нулевую проверку, если утверждение:
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
предложения является просто распаковка из необязательного, лучше использоватьguard
вместо этого оператор.Добавьте метку без текста и с цветом фона, соответствующим размеру кадра (например, высота = 1). Сделайте это через код или в построителе интерфейса.
источник