Bir UIViewController
. Programlı olarak oluşturulmuş görünümlerinden birinde nasıl çizgi çizerim?
Bir UIViewController
. Programlı olarak oluşturulmuş görünümlerinden birinde nasıl çizgi çizerim?
Yanıtlar:
İki yaygın teknik vardır.
Kullanarak CAShapeLayer
:
Bir oluşturun UIBezierPath
(koordinatları istediğiniz gibi değiştirin):
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
Bir oluşturun CAShapeLayer
o kullanımları o UIBezierPath
:
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [path CGPath];
shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
shapeLayer.lineWidth = 3.0;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
Bunu CAShapeLayer
görünümünüzün katmanına ekleyin:
[self.view.layer addSublayer:shapeLayer];
Xcode'un önceki sürümlerinde, QuartzCore.framework'ü projenizin "Link Binary with Libraries" e manuel olarak eklemeniz ve <QuartzCore/QuartzCore.h>
başlığı .m dosyanıza aktarmanız gerekiyordu, ancak artık gerekli değil ("Modülleri Etkinleştir" ve "Bağlantı Çerçeveler Otomatik olarak "derleme ayarları açılır).
Diğer yaklaşım, alt sınıflamak UIView
ve ardından yöntemde CoreGraphics çağrılarını kullanmaktır drawRect
:
Bir UIView
alt sınıf oluşturun ve drawRect
çizginizi çizen bir alt sınıf tanımlayın .
Bunu Core Graphics ile yapabilirsiniz:
- (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);
}
Veya kullanarak 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];
}
Ardından, bu görünüm sınıfını NIB / film şeridiniz veya görünümünüz için temel sınıf olarak kullanabilir veya görünüm denetleyicinizin bunu bir alt görünüm olarak programlı bir şekilde eklemesini sağlayabilirsiniz:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
pathView.backgroundColor = [UIColor clearColor];
[self.view addSubview: pathView];
Yukarıdaki iki yaklaşımın Swift yorumları aşağıdaki gibidir:
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
alt sınıf:
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()
}
}
Ve bunu görünüm hiyerarşinize ekleyin:
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
Yukarıda, PathView
programlı olarak ekliyorum , ancak bunu IB aracılığıyla da ekleyebilir ve path
programlı olarak ayarlayabilirsiniz .
shapeLayer.lineCap = kCALineCapRound;
UIBezierPath
, tekrarlanan addLineToPoint
/ addLine(to:)
çağrıları olan bir tek hattınız da olabilir . Daha sonra shapeLayer.lineJoin = kCALineJoinRound
ya kCALineJoinBevel
da ya da tercihinizi seçebilirsiniz kCALineJoinMiter
.
Bir UIView oluşturun ve bunu görünüm denetleyicinizin görünümünün bir alt görünümü olarak ekleyin. Bu alt görünümün yüksekliğini veya genişliğini, bir çizgi gibi görünecek şekilde çok küçük olacak şekilde değiştirebilirsiniz. Çapraz bir çizgi çizmeniz gerekirse, alt görünümleri dönüştürme özelliğini değiştirebilirsiniz.
örneğin siyah yatay çizgi çizin. Bu, görünüm denetleyicinizin uygulamasından çağrılır
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)
İşte yararlı bulabileceğiniz harika bir teknik: Objective-C'de alt sınıflardan kaçınmak için çizim için blokları kullanma
Makalenin genel amaçlı görünüm alt sınıfını projenize dahil edin, ardından bu, anında bir çizgi çizen bir görünüm oluşturmak için görünüm denetleyicinize koyabileceğiniz kod türüdür:
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];
Çizgi çizmek için UIImageView'ı kullanabilirsiniz.
Bununla birlikte, alt sınıflandırma atlamaya izin verir. Ve Core Graphics'e biraz eğilimli olduğum için hala kullanabilirim. Sadece koyabilirsiniz -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();
Rob'un cevabına ek olarak, Bir çabukluk için, üçüncü yaklaşım bir UIImageView
- onu örtmek - xib görünümünü kullanmaktır. (Bu, xcode 5'te xib'e sürüklendiğinde varsayılan UIImageView görünümüdür)
Şerefe ve +1!
Gerçekten yapmamalısınız, ancak herhangi bir nedenden dolayı size mantıklı geliyorsa, DelegateDrawView
örneğin, aşağıdaki gibi bir yöntemi uygulayan bir temsilciyi alan bir UIView alt sınıfı oluşturabilirsiniz.
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
ve sonra yöntemlerde - [DelegateDrawView drawRect:]
temsilci yönteminizi çağırmalısınız.
Ama neden denetleyicinize görüntüleme kodunu yerleştirmek istersiniz?
İki köşesi arasına bir çizgi çizen bir UIView alt sınıfı oluşturmakta daha iyi olursunuz, hangi ikisini ayarlamak için bir özelliğe sahip olabilir ve ardından görünümü istediğiniz yere konumlandırabilirsiniz.
Görüşünüzün içini çizmek çok basit, @ ROB ilk yöntemi benim aldığım 2 yöntemi söyledi.
Kodu kopyalayıp istediğiniz yere yapıştırın.
-(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);
}
Parmağın hareket ettiği bir çizgi gibi çizecek