Mam UIViewController
. Jak narysować linię w jednym z jej widoków utworzonych programowo?
ios
objective-c
uiview
uikit
mkc842
źródło
źródło
Odpowiedzi:
Istnieją dwie powszechne techniki.
Używając
CAShapeLayer
:Utwórz
UIBezierPath
(zamień współrzędne na dowolne):UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(10.0, 10.0)]; [path addLineToPoint:CGPointMake(100.0, 100.0)];
Utwórz,
CAShapeLayer
który używa tegoUIBezierPath
:CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [path CGPath]; shapeLayer.strokeColor = [[UIColor blueColor] CGColor]; shapeLayer.lineWidth = 3.0; shapeLayer.fillColor = [[UIColor clearColor] CGColor];
Dodaj to
CAShapeLayer
do warstwy widoku:[self.view.layer addSublayer:shapeLayer];
W poprzednich wersjach Xcode trzeba było ręcznie dodać QuartzCore.framework do elementu „Połącz
<QuartzCore/QuartzCore.h>
plik binarny z bibliotekami” projektu i zaimportować nagłówek do pliku .m, ale nie jest to już konieczne (jeśli masz opcje „Włącz moduły” i „Połącz Struktury automatycznie „włączone ustawienia kompilacji).Drugim podejściem jest podklasa,
UIView
a następnie użycie wywołań CoreGraphics wdrawRect
metodzie:Utwórz
UIView
podklasę i zdefiniuj,drawRect
która rysuje twoją linię.Możesz to zrobić z 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); }
Lub za pomocą
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]; }
Następnie możesz użyć tej klasy widoku jako klasy bazowej dla swojego NIB / serii ujęć lub widoku, albo możesz programowo dodać ją jako widok podrzędny do kontrolera widoku:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds]; pathView.backgroundColor = [UIColor clearColor]; [self.view addSubview: pathView];
Szybkie wersje dwóch powyższych podejść są następujące:
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
podklasa: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() } }
I dodaj go do swojej hierarchii widoków:
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
Powyżej
PathView
dodaję programowo, ale możesz też dodać go przez IB i po prostu ustawićpath
programowo.źródło
shapeLayer.lineCap = kCALineCapRound;
UIBezierPath
, z powtórzonymiaddLineToPoint
/addLine(to:)
wywołania. Następnie możesz wybrać, czy wolisz,shapeLayer.lineJoin = kCALineJoinRound
czykCALineJoinBevel
lubkCALineJoinMiter
.Utwórz widok UIView i dodaj go jako widok podrzędny widoku kontrolera widoku. Możesz zmodyfikować wysokość lub szerokość tego widoku podrzędnego, aby był bardzo mały, aby wyglądał jak linia. Jeśli chcesz narysować linię ukośną, możesz zmodyfikować właściwość transformacji widoków podrzędnych.
np. narysuj czarną poziomą linię. Jest to wywoływane z implementacji kontrolera widoku
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)]; lineView.backgroundColor = [UIColor blackColor]; [self.view addSubview:lineView];
źródło
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)
źródło
Oto fajna technika, która może Ci się przydać: Używanie bloków do rysowania, aby uniknąć tworzenia podklas w Objective-C
Uwzględnij podklasę widoku ogólnego przeznaczenia w swoim projekcie, a następnie w kontrolerze widoku możesz umieścić taki kod, aby w locie utworzyć widok rysujący linię:
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];
źródło
Możesz użyć UIImageView do rysowania linii.
Pozwala jednak na pominięcie podklas. A ponieważ jestem mało skłonny do Core Graphics, nadal mogę go używać. Możesz to po prostu włożyć -
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();
Dodatek do odpowiedzi Roba, Trzecim podejściem jest użycie
UIImageView
- zakryj to - widoku xib. (To jest domyślny wygląd UIImageView po przeciągnięciu na xib w xcode 5)Pozdrawiam i +1!
źródło
Nie powinieneś, ale jeśli z jakiegoś powodu ma to dla ciebie sens, możesz utworzyć podklasę UIView, nazywaną
DelegateDrawView
na przykład, która przyjmuje delegata, który implementuje metodę taką jak- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
a następnie w metodach -
[DelegateDrawView drawRect:]
należy wywołać metodę delegata.Ale dlaczego miałbyś chcieć umieścić kod widoku w kontrolerze.
Lepiej jest utworzyć podklasę UIView, która rysuje linię między dwoma jej rogami, możesz ustawić właściwość, aby ustawić które z nich, a następnie ustawić widok tam, gdzie chcesz, od kontrolera widoku.
źródło
Aby narysować wnętrze twojego widoku jest bardzo proste, @ Mr.ROB powiedział 2 metodę, którą wybrałem pierwszą metodę.
Po prostu skopiuj, wklej kod tam, gdzie chcesz.
-(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); }
Będzie rysować jak linia, po której porusza się palec
źródło