J'ai un UIViewController
. Comment tracer une ligne dans l'une de ses vues créées par programme?
Il existe deux techniques courantes.
Utiliser CAShapeLayer
:
Créez un UIBezierPath
(remplacez les coordonnées par ce que vous voulez):
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
Créez un CAShapeLayer
qui utilise ce UIBezierPath
:
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
Ajoutez ce CAShapeLayer
au calque de votre vue:
[self.view.layer addSublayer:shapeLayer];
Dans les versions précédentes de Xcode, vous deviez ajouter manuellement QuartzCore.framework au "Link Binary with Libraries" de votre projet et importer le fichier <QuartzCore/QuartzCore.h>
en-tête dans votre fichier .m, mais ce n’est plus nécessaire (si les paramètres de construction "Activer les modules" et "Lier automatiquement les cadres" sont activés).
L’autre approche consiste à sous-classer UIView
et à utiliser ensuite CoreGraphics appelle dans la méthode drawRect
:
Créez une sous-classe UIView
et définissez un drawRect
qui dessine votre ligne.
Vous pouvez le faire avec 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);
}
Ou en utilisant 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];
}
Vous pouvez ensuite utiliser cette classe de vue comme classe de base pour votre NIB/storyboard ou votre vue, ou vous pouvez demander à votre contrôleur de vue de l'ajouter par programmation en tant que sous-vue:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
pathView.backgroundColor = [UIColor clearColor];
[self.view addSubview: pathView];
Les rendus Swift des deux approches ci-dessus sont les suivants:
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
sous-classe:
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()
}
}
Et ajoutez-le à votre hiérarchie de vues:
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
Ci-dessus, j'ajoute PathView
par programmation, mais vous pouvez aussi l'ajouter via IB, et définissez simplement sa path
par programmation.
Créez un UIView et ajoutez-le en tant que sous-vue de la vue de votre contrôleur de vue. Vous pouvez modifier la hauteur ou la largeur de cette sous-vue pour qu'elle soit très petite, afin qu'elle ressemble à une ligne. Si vous devez tracer une ligne diagonale, vous pouvez modifier la propriété de transformation des sous-vues.
par exemple. tracer une ligne horizontale noire. Ceci est appelé depuis l'implémentation de votre contrôleur de vue
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)]; lineView.backgroundColor = [UIColor blackColor]; [self.view addSubview:lineView];
Voici une technique intéressante qui pourrait vous être utile: tilisation de blocs de dessin pour éviter les sous-classes dans Objective-C
Incluez la sous-classe de vue à usage général de l'article dans votre projet. Il s'agit du type de code que vous pouvez mettre dans votre contrôleur de vue pour créer une vue à la volée qui trace une ligne:
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];
Vous pouvez utiliser UIImageView pour dessiner des lignes.
Cela permet toutefois de sauter le sous-classement. Et comme je suis peu enclin à Core Graphics, je peux toujours l'utiliser. Vous pouvez simplement le mettre dans - 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();
Ajout à la réponse de Rob, Pour un coup de œil, la troisième approche consiste à utiliser un UIImageView
- le recouvrir - la vue de xib. (C’est l’apparence par défaut de UIImageView lorsqu’il est glissé sur xib dans xcode 5)
Vive et +1!
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)
Vous ne devriez pas vraiment, mais si pour une raison quelconque cela vous semble logique, vous pouvez créer une sous-classe d’UIView, appelée DelegateDrawView par exemple, qui prend un délégué qui implémente une méthode telle que
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
puis dans les méthodes - [DelegateDrawView drawRect:], vous appelez votre méthode déléguée.
Mais pourquoi voudriez-vous mettre le code de vue dans votre contrôleur?.
Vous feriez mieux de créer une sous-classe de UIView, qui trace une ligne entre deux de ses coins, vous pouvez avoir une propriété pour définir laquelle et ensuite positionner la vue où vous le souhaitez depuis votre contrôleur de vue.
Dessiner à l'intérieur de votre vue est très simple, @ Mr.ROB a déclaré 2 méthode j'ai pris la première méthode.
Il suffit de copier coller le code où vous le voulez.
-(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);
}
Il va tracer comme une ligne, où le doigt se déplace