Ich habe eine UIViewController
. Wie zeichne ich eine Linie in einer der programmgesteuert erstellten Ansichten?
Ich habe eine UIViewController
. Wie zeichne ich eine Linie in einer der programmgesteuert erstellten Ansichten?
Antworten:
Es gibt zwei gängige Techniken.
Verwenden von CAShapeLayer
:
Erstellen Sie eine UIBezierPath
(ersetzen Sie die Koordinaten durch was auch immer Sie wollen):
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
Erstellen Sie eine CAShapeLayer
, die das verwendet UIBezierPath
:
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
Fügen CAShapeLayer
Sie das der Ebene Ihrer Ansicht hinzu:
[self.view.layer addSublayer:shapeLayer];
In früheren Versionen von Xcode mussten Sie QuartzCore.framework manuell zum "Link Binary with Libraries" Ihres Projekts hinzufügen und den <QuartzCore/QuartzCore.h>
Header in Ihre .m-Datei importieren. Dies ist jedoch nicht mehr erforderlich (wenn Sie über "Enable Modules" und "Link" verfügen Frameworks automatisch "Build-Einstellungen aktiviert).
Der andere Ansatz besteht darin UIView
, CoreGraphics- Aufrufe in der drawRect
Methode zu unterklassifizieren und dann zu verwenden :
Erstellen Sie eine UIView
Unterklasse und definieren Sie eine drawRect
, die Ihre Linie zeichnet.
Sie können dies mit Core Graphics tun:
- (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);
}
Oder mit 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];
}
Anschließend können Sie diese Ansichtsklasse entweder als Basisklasse für Ihre NIB / Ihr Storyboard oder Ihre Ansicht verwenden oder Ihren Ansichts-Controller programmgesteuert als Unteransicht hinzufügen lassen:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
pathView.backgroundColor = [UIColor clearColor];
[self.view addSubview: pathView];
Die Swift-Wiedergaben der beiden obigen Ansätze lauten wie folgt:
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
Unterklasse:
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()
}
}
Und fügen Sie es Ihrer Ansichtshierarchie hinzu:
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
Oben PathView
füge ich programmgesteuert hinzu , aber Sie können es auch über IB hinzufügen und es einfach path
programmgesteuert einstellen .
shapeLayer.lineCap = kCALineCapRound;
UIBezierPath
mit wiederholten addLineToPoint
/ addLine(to:)
Anrufen verwenden. Dann können Sie auswählen, ob Sie shapeLayer.lineJoin = kCALineJoinRound
oder kCALineJoinBevel
oder bevorzugen kCALineJoinMiter
.
Erstellen Sie eine UIView und fügen Sie sie als Unteransicht der Ansicht Ihres View Controllers hinzu. Sie können die Höhe oder Breite dieser Unteransicht so ändern, dass sie sehr klein ist, sodass sie wie eine Linie aussieht. Wenn Sie eine diagonale Linie zeichnen müssen, können Sie die Transformationseigenschaft für Unteransichten ändern.
zB schwarze horizontale Linie zeichnen. Dies wird in der Implementierung Ihres View Controllers aufgerufen
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)
Hier ist eine coole Technik, die Sie vielleicht nützlich finden: Verwenden von Blöcken zum Zeichnen, um Unterklassen in Objective-C zu vermeiden
Fügen Sie die Unterklasse für allgemeine Ansichten des Artikels in Ihr Projekt ein. Dann können Sie diese Art von Code in Ihren Ansichts-Controller einfügen, um im laufenden Betrieb eine Ansicht zu erstellen, die eine Linie zeichnet:
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];
Mit UIImageView können Sie Linien zeichnen.
Es erlaubt jedoch, die Unterklassifizierung zu überspringen. Und da ich wenig zu Core Graphics neige, kann ich es immer noch verwenden. Sie können es einfach eingeben -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();
Ergänzung zu Robs Antwort: Für einen schnellen Schritt besteht der dritte Ansatz darin, UIImageView
die Ansicht von xib zu vertuschen. (Dies ist das Standard-UIImageView-Erscheinungsbild beim Ziehen auf xib in xcode 5)
Prost und +1!
Sie sollten es nicht wirklich tun, aber wenn es aus irgendeinem Grund für Sie sinnvoll ist, können Sie eine Unterklasse von UIView erstellen, die DelegateDrawView
beispielsweise aufgerufen wird und einen Delegaten benötigt, der eine Methode wie implementiert
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
und dann in den Methoden - [DelegateDrawView drawRect:]
Sie sollten Ihre Delegate-Methode aufrufen.
Aber warum sollten Sie Ansichtscode in Ihren Controller einfügen?
Es ist besser, eine Unterklasse von UIView zu erstellen, die eine Linie zwischen zwei ihrer Ecken zeichnet. Sie können eine Eigenschaft festlegen, um welche zwei festzulegen, und dann die Ansicht an der gewünschten Position von Ihrem Ansichts-Controller aus positionieren.
In Ihre Ansicht zu zeichnen ist sehr einfach. @ Mr.ROB sagte 2 Methode, ich habe die erste Methode gewählt.
Kopieren Sie einfach den Code, wo Sie ihn haben möchten.
-(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);
}
Es wird wie eine Linie gezeichnet, wo sich der Finger bewegt