Tengo un UIViewController
. ¿Cómo trazo una línea en una de sus vistas creadas mediante programación?
Tengo un UIViewController
. ¿Cómo trazo una línea en una de sus vistas creadas mediante programación?
Respuestas:
Hay dos técnicas comunes.
Usando CAShapeLayer
:
Crea un UIBezierPath
(reemplaza las coordenadas con lo que quieras):
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
Crea un CAShapeLayer
que use eso UIBezierPath
:
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
Agregue eso CAShapeLayer
a la capa de su vista:
[self.view.layer addSublayer:shapeLayer];
En versiones anteriores de Xcode, tenía que agregar manualmente QuartzCore.framework al "Enlace binario con bibliotecas" de su proyecto e importar el <QuartzCore/QuartzCore.h>
encabezado en su archivo .m, pero eso ya no es necesario (si tiene "Activar módulos" y "Enlace Frameworks Automáticamente "configuración de compilación activada).
El otro enfoque es crear una subclase UIView
y luego usar llamadas a CoreGraphics en el drawRect
método:
Cree una UIView
subclase y defina una drawRect
que dibuje su línea.
Puede hacer esto con Core Graphics:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextSetLineWidth(context, 3.0);
CGContextMoveToPoint(context, 10.0, 10.0);
CGContextAddLineToPoint(context, 100.0, 100.0);
CGContextDrawPath(context, kCGPathStroke);
}
O usando UIKit
:
- (void)drawRect:(CGRect)rect {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
path.lineWidth = 3;
[[UIColor blueColor] setStroke];
[path stroke];
}
Luego, puede usar esta clase de vista como la clase base para su NIB / storyboard o vista, o puede hacer que su controlador de vista lo agregue programáticamente como una subvista:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
pathView.backgroundColor = [UIColor clearColor];
[self.view addSubview: pathView];
Las interpretaciones Swift de los dos enfoques anteriores son las siguientes:
CAShapeLayer
:
// create path
let path = UIBezierPath()
path.move(to: CGPoint(x: 10, y: 10))
path.addLine(to: CGPoint(x: 100, y: 100))
// Create a `CAShapeLayer` that uses that `UIBezierPath`:
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 3
// Add that `CAShapeLayer` to your view's layer:
view.layer.addSublayer(shapeLayer)
UIView
subclase:
class PathView: UIView {
var path: UIBezierPath? { didSet { setNeedsDisplay() } }
var pathColor: UIColor = .blue { didSet { setNeedsDisplay() } }
override func draw(_ rect: CGRect) {
// stroke the path
pathColor.setStroke()
path?.stroke()
}
}
Y agréguelo a su jerarquía de vista:
let pathView = PathView()
pathView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(pathView)
NSLayoutConstraint.activate([
pathView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
pathView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
pathView.topAnchor.constraint(equalTo: view.topAnchor),
pathView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
pathView.backgroundColor = .clear
let path = UIBezierPath()
path.move(to: CGPoint(x: 10, y: 10))
path.addLine(to: CGPoint(x: 100, y: 100))
path.lineWidth = 3
pathView.path = path
Arriba, estoy agregando PathView
programáticamente, pero también puede agregarlo a través de IB, y simplemente configurarlo path
programáticamente.
shapeLayer.lineCap = kCALineCapRound;
UIBezierPath
, con llamadas addLineToPoint
/ repetidas addLine(to:)
. Entonces puede elegir si prefiere shapeLayer.lineJoin = kCALineJoinRound
o kCALineJoinBevel
o kCALineJoinMiter
.
Cree una UIView y agréguela como una subvista de la vista de su controlador de vista. Puede modificar el alto o el ancho de esta subvista para que sea muy pequeño para que se vea como una línea. Si necesita dibujar una línea diagonal, puede modificar la propiedad de transformación de las subvistas.
por ejemplo, dibuje una línea horizontal negra. Esto se llama desde la implementación de su controlador de vista
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];
Swift 3:
let path = UIBezierPath()
path.move(to: CGPoint(x: 10, y: 10))
path.addLine(to: CGPoint(x: 100, y: 100))
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.lineWidth = 3.0
view.layer.addSublayer(shapeLayer)
Aquí hay una técnica interesante que puede resultarle útil: usar bloques para dibujar para evitar subclases en Objective-C
Incluya la subclase de vista de propósito general del artículo en su proyecto, entonces este es el tipo de código que puede poner en su controlador de vista para crear una vista sobre la marcha que dibuje una línea:
DrawView* drawableView = [[[DrawView alloc] initWithFrame:CGRectMake(0,0,320,50)] autorelease];
drawableView.drawBlock = ^(UIView* v,CGContextRef context)
{
CGPoint startPoint = CGPointMake(0,v.bounds.size.height-1);
CGPoint endPoint = CGPointMake(v.bounds.size.width,v.bounds.size.height-1);
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
CGContextSetLineWidth(context, 1);
CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
CGContextStrokePath(context);
};
[self.view addSubview:drawableView];
Puede usar UIImageView para dibujar líneas.
Sin embargo, permite omitir la subclasificación. Y como estoy poco inclinado a Core Graphics, todavía puedo usarlo. Puedes ponerlo en ...ViewDidLoad
UIGraphicsBeginImageContext(self.view.frame.size);
[self.myImageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), 50, 50);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), 200, 200);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.myImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Además de la respuesta de Rob, para una rápida, el tercer enfoque es usar un UIImageView
- cubrir con él - la vista de xib. (Esa es la apariencia predeterminada de UIImageView cuando se arrastra en xib en xcode 5)
Saludos y +1!
Realmente no debería, pero si por alguna razón tiene sentido para usted, podría crear una subclase de UIView, llamada DelegateDrawView
por ejemplo, que toma un delegado que implementa un método como
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
y luego en los métodos, [DelegateDrawView drawRect:]
debe llamar a su método delegado.
Pero, ¿por qué querrías poner el código de vista en tu controlador?
Es mejor crear una subclase de UIView, que dibuje una línea entre dos de sus esquinas, puede tener una propiedad para establecer cuáles dos y luego colocar la vista donde la desee desde su controlador de vista.
Dibujar dentro de su vista es muy simple, @ Mr.ROB dijo 2 método Tomé el primer método.
Simplemente copie y pegue el código donde lo desee.
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
startingPoint = [touch locationInView:self.view];
NSLog(@"Touch starting point = x : %f Touch Starting Point = y : %f", touchPoint.x, touchPoint.y);
}
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
touchPoint = [touch locationInView:self.view];
NSLog(@"Touch end point =x : %f Touch end point =y : %f", touchPoint.x, touchPoint.y);
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
touchPoint = [touch locationInView:self.view];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
[path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)];
startingPoint=touchPoint;
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor redColor] CGColor];
[self.view.layer addSublayer:shapeLayer];
NSLog(@"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);
[self.view setNeedsDisplay];
}
- (void)tapGestureRecognizer:(UIGestureRecognizer *)recognizer {
CGPoint tappedPoint = [recognizer locationInView:self.view];
CGFloat xCoordinate = tappedPoint.x;
CGFloat yCoordinate = tappedPoint.y;
NSLog(@"Touch Using UITapGestureRecognizer x : %f y : %f", xCoordinate, yCoordinate);
}
Dibujará como una línea, donde el dedo se mueve yendo