Necesito dibujar una línea horizontal en una UIView. ¿Cuál es la forma más sencilla de hacerlo? Por ejemplo, quiero dibujar una línea horizontal negra en y-coord = 200.
Aquí está la solución completa y fácil para tener correctamente una línea de un solo píxel, en todo iOS, y hacerlo fácil en el guión gráfico: stackoverflow.com/a/26525466/294884
Fattie
Respuestas:
122
La forma más sencilla en su caso (línea horizontal) es agregar una subvista con un marco y un color de fondo negro [0, 200, 320, 1].
Ejemplo de código (espero que no haya errores, lo escribí sin 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...
Otra forma es crear una clase que dibujará una línea en su método drawRect (puedes ver mi ejemplo de código para esto aquí ).
Haga esto sin ningún código en Storyboard. Es más fácil y mejor.
coolcool1994
3
@ coolcool1994, ¿no te has dado cuenta de que "NO estoy usando Interface Builder"? requisito en la pregunta?
Michael Kessler
312
Quizás esto sea un poco tarde, pero quiero agregar que hay una mejor manera. Usar UIView es simple, pero relativamente lento. Este método anula cómo se dibuja la vista y es más rápido:
- (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);
}
Si este código se usa en una UIView, ¿las coordenadas de esta muestra son relativas a los límites de la vista o a toda la pantalla?
ChrisP
¿No hace falta llamar CGContextBeginPath(context);antes CGContextMoveToPoint(...);?
i_am_jorf
37
Usar una vista para hacerlo no es demasiado horrible. Facilita las cosas, por ejemplo, al hacer animaciones implícitas durante los cambios de orientación. Si es solo una, otra UIView no es tan cara y el código es mucho más simple.
i_am_jorf
Además, puede obtener límites y puntos medios con estos códigos: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994
1
Bien, el comentario de que es "lento" no tiene sentido. Hay una gran cantidad de UIViews simples en la pantalla en cualquier momento. Tenga en cuenta que dibujar UN carácter de texto (!), Con todo el procesamiento que implica, los pantanos dibujan una UIView llena.
Fattie
30
Swift 3 y Swift 4
Así es como puede dibujar una línea gris al final de su vista (la misma idea que la respuesta de b123400)
El "contexto si se deja" falla cuando se llama desde viewDidLayoutSubviews.
Oscar
14
Simplemente agregue una etiqueta sin texto y con color de fondo. Establezca las coordenadas de su elección y también la altura y el ancho. Puede hacerlo manualmente o con Interface Builder.
E inicializó los objetos pathArray y dictPAth que se utilizarán para el dibujo lineal. Estoy escribiendo la parte principal del código de mi propio proyecto:
- (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];
}
si el motivo de la ifcláusula es simplemente desempaquetar de lo opcional, prefiera usar una guarddeclaración en su lugar.
Julio Flores
-1
Agregue una etiqueta sin texto y con el color de fondo correspondiente al tamaño del marco (p. Ej., Altura = 1). Hágalo a través del código o en el generador de interfaces.
Respuestas:
La forma más sencilla en su caso (línea horizontal) es agregar una subvista con un marco y un color de fondo negro
[0, 200, 320, 1]
.Ejemplo de código (espero que no haya errores, lo escribí sin 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...
Otra forma es crear una clase que dibujará una línea en su método drawRect (puedes ver mi ejemplo de código para esto aquí ).
fuente
Quizás esto sea un poco tarde, pero quiero agregar que hay una mejor manera. Usar UIView es simple, pero relativamente lento. Este método anula cómo se dibuja la vista y es más rápido:
- (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); }
fuente
CGContextBeginPath(context);
antesCGContextMoveToPoint(...);
?Swift 3 y Swift 4
Así es como puede dibujar una línea gris al final de su vista (la misma idea que la respuesta de 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() } } }
fuente
Simplemente agregue una etiqueta sin texto y con color de fondo. Establezca las coordenadas de su elección y también la altura y el ancho. Puede hacerlo manualmente o con Interface Builder.
fuente
Puede usar la clase UIBezierPath para esto:
Y puede dibujar tantas líneas como desee:
He subclasificado UIView:
@interface MyLineDrawingView() { NSMutableArray *pathArray; NSMutableDictionary *dict_path; CGPoint startPoint, endPoint; } @property (nonatomic,retain) UIBezierPath *myPath; @end
E inicializó los objetos pathArray y dictPAth que se utilizarán para el dibujo lineal. Estoy escribiendo la parte principal del código de mi propio proyecto:
- (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]; }
método touchesBegin:
UITouch *touch = [touches anyObject]; startPoint = [touch locationInView:self]; myPath=[[UIBezierPath alloc]init]; myPath.lineWidth = currentSliderValue*2; dict_path = [[NSMutableDictionary alloc] init];
touchchesMoved Método:
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];
método touchesEnded:
NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path]; [pathArray addObject:tempDict]; [dict_path removeAllObjects]; [self setNeedsDisplay];
fuente
Otra posibilidad (y aún más corta). Si está dentro de drawRect, algo como lo siguiente:
[[UIColor blackColor] setFill]; UIRectFill((CGRect){0,200,rect.size.width,1});
fuente
Basado en la respuesta de Guy Daher.
Trato de evitar usar? porque puede provocar un bloqueo de la aplicación si GetCurrentContext () devuelve nil.
No haría ninguna comprobación si la declaración:
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() } } }
fuente
if
cláusula es simplemente desempaquetar de lo opcional, prefiera usar unaguard
declaración en su lugar.Agregue una etiqueta sin texto y con el color de fondo correspondiente al tamaño del marco (p. Ej., Altura = 1). Hágalo a través del código o en el generador de interfaces.
fuente