Muszę narysować poziomą linię w UIView. Jaki jest najłatwiejszy sposób na zrobienie tego. Na przykład chcę narysować czarną poziomą linię przy y -coor = 200.
Oto kompletne i łatwe rozwiązanie, aby poprawnie mieć linię jednopikselową we wszystkich systemach iOS i ułatwić tworzenie scenorysu: stackoverflow.com/a/26525466/294884
Fattie
Odpowiedzi:
122
Najłatwiej w twoim przypadku (linia pozioma) jest dodanie widoku podrzędnego z czarnym kolorem tła i ramką [0, 200, 320, 1].
Przykładowy kod (mam nadzieję, że nie ma błędów - napisałem bez Xcode):
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];
[lineView release];
// You might also keep a reference to this view // if you are about to change its coordinates.// Just create a member and a property for this...
Innym sposobem jest utworzenie klasy, która będzie narysować linię w swojej metodzie drawRect (widać mój przykładowy kod dla tego tutaj ).
Zrób to bez żadnego kodu w Storyboard. Jest łatwiej i lepiej.
coolcool1994
3
@ coolcool1994, czy nie zauważyłeś „NIE używam programu Interface Builder”. wymóg w pytaniu?
Michael Kessler
312
Może to trochę za późno, ale chcę dodać, że jest lepszy sposób. Korzystanie z UIView jest proste, ale stosunkowo wolne. Ta metoda zastępuje sposób, w jaki widok sam się rysuje i jest szybsza:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
// Draw them with a 2.0 stroke width so they are a bit more visible.CGContextSetLineWidth(context, 2.0f);
CGContextMoveToPoint(context, 0.0f, 0.0f); //start at this pointCGContextAddLineToPoint(context, 20.0f, 20.0f); //draw to this point// and now draw the Path!CGContextStrokePath(context);
}
Jeśli ten kod jest używany w UIView, to czy współrzędne w tym przykładzie odnoszą się do granic widoku czy całego ekranu?
ChrisP,
Czy nie trzeba CGContextBeginPath(context);wcześniej dzwonić CGContextMoveToPoint(...);?
i_am_jorf
37
Używanie widoku do tego nie jest straszne. Ułatwia to na przykład wykonywanie niejawnych animacji podczas zmiany orientacji. Jeśli to tylko jeden, kolejny UIView nie jest wcale taki drogi, a kod jest znacznie prostszy.
i_am_jorf
Ponadto za pomocą tych kodów można uzyskać granice i punkt środkowy: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994
1
Racja, komentarz, że jest „wolny”, nie jest rozsądny. W dowolnym momencie na ekranie pojawia się ogromna liczba prostych podglądów UIV. Zwróć uwagę, że rysowanie JEDNEGO (!) Znaku tekstowego, wraz z całym przetwarzaniem, powoduje, że rysuje wypełniony UIView.
Fattie
30
Swift 3 i Swift 4
W ten sposób możesz narysować szarą linię na końcu widoku (ten sam pomysł, co odpowiedź b123400)
Kontekst „if let” kończy się niepowodzeniem po wywołaniu z viewDidLayoutSubviews.
Oscar
14
Po prostu dodaj etykietę bez tekstu iz kolorem tła. Ustaw wybrane współrzędne, a także wysokość i szerokość. Możesz to zrobić ręcznie lub za pomocą Interface Builder.
Zainicjowałem obiekty pathArray i dictPAth, które będą używane do rysowania linii. Piszę główną część kodu z własnego projektu:
- (void)drawRect:(CGRect)rect
{
for(NSDictionary *_pathDict in pathArray)
{
[((UIColor *)[_pathDict valueForKey:@"color"]) setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)[[_pathDict valueForKey:@"path"]strokeWithBlendMode:kCGBlendModeNormalalpha:1.0];
}
[[dict_path objectForKey:@"color"]setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)[[dict_path objectForKey:@"path"]strokeWithBlendMode:kCGBlendModeNormalalpha:1.0];
}
Odpowiedzi:
Najłatwiej w twoim przypadku (linia pozioma) jest dodanie widoku podrzędnego z czarnym kolorem tła i ramką
[0, 200, 320, 1]
.Przykładowy kod (mam nadzieję, że nie ma błędów - napisałem bez Xcode):
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)]; lineView.backgroundColor = [UIColor blackColor]; [self.view addSubview:lineView]; [lineView release]; // You might also keep a reference to this view // if you are about to change its coordinates. // Just create a member and a property for this...
Innym sposobem jest utworzenie klasy, która będzie narysować linię w swojej metodzie drawRect (widać mój przykładowy kod dla tego tutaj ).
źródło
Może to trochę za późno, ale chcę dodać, że jest lepszy sposób. Korzystanie z UIView jest proste, ale stosunkowo wolne. Ta metoda zastępuje sposób, w jaki widok sam się rysuje i jest szybsza:
- (void)drawRect:(CGRect)rect { [super drawRect:rect]; CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); // Draw them with a 2.0 stroke width so they are a bit more visible. CGContextSetLineWidth(context, 2.0f); CGContextMoveToPoint(context, 0.0f, 0.0f); //start at this point CGContextAddLineToPoint(context, 20.0f, 20.0f); //draw to this point // and now draw the Path! CGContextStrokePath(context); }
źródło
CGContextBeginPath(context);
wcześniej dzwonićCGContextMoveToPoint(...);
?Swift 3 i Swift 4
W ten sposób możesz narysować szarą linię na końcu widoku (ten sam pomysł, co odpowiedź b123400)
class CustomView: UIView { override func draw(_ rect: CGRect) { super.draw(rect) if let context = UIGraphicsGetCurrentContext() { context.setStrokeColor(UIColor.gray.cgColor) context.setLineWidth(1) context.move(to: CGPoint(x: 0, y: bounds.height)) context.addLine(to: CGPoint(x: bounds.width, y: bounds.height)) context.strokePath() } } }
źródło
Po prostu dodaj etykietę bez tekstu iz kolorem tła. Ustaw wybrane współrzędne, a także wysokość i szerokość. Możesz to zrobić ręcznie lub za pomocą Interface Builder.
źródło
Możesz użyć klasy UIBezierPath w tym celu:
I możesz narysować tyle linii, ile chcesz:
Mam podklasę UIView:
@interface MyLineDrawingView() { NSMutableArray *pathArray; NSMutableDictionary *dict_path; CGPoint startPoint, endPoint; } @property (nonatomic,retain) UIBezierPath *myPath; @end
Zainicjowałem obiekty pathArray i dictPAth, które będą używane do rysowania linii. Piszę główną część kodu z własnego projektu:
- (void)drawRect:(CGRect)rect { for(NSDictionary *_pathDict in pathArray) { [((UIColor *)[_pathDict valueForKey:@"color"]) setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor) [[_pathDict valueForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; } [[dict_path objectForKey:@"color"] setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor) [[dict_path objectForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; }
dotyka metody początkowej:
UITouch *touch = [touches anyObject]; startPoint = [touch locationInView:self]; myPath=[[UIBezierPath alloc]init]; myPath.lineWidth = currentSliderValue*2; dict_path = [[NSMutableDictionary alloc] init];
dotyka Metoda przeniesiona:
UITouch *touch = [touches anyObject]; endPoint = [touch locationInView:self]; [myPath removeAllPoints]; [dict_path removeAllObjects];// remove prev object in dict (this dict is used for current drawing, All past drawings are managed by pathArry) // actual drawing [myPath moveToPoint:startPoint]; [myPath addLineToPoint:endPoint]; [dict_path setValue:myPath forKey:@"path"]; [dict_path setValue:strokeColor forKey:@"color"]; // NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path]; // [pathArray addObject:tempDict]; // [dict_path removeAllObjects]; [self setNeedsDisplay];
Metoda dotknięcia Ended:
NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path]; [pathArray addObject:tempDict]; [dict_path removeAllObjects]; [self setNeedsDisplay];
źródło
Jeszcze jedna (i jeszcze krótsza) możliwość. Jeśli jesteś w drawRect, coś takiego:
[[UIColor blackColor] setFill]; UIRectFill((CGRect){0,200,rect.size.width,1});
źródło
Na podstawie odpowiedzi Guya Dahera.
Próbuję unikać używania? ponieważ może to spowodować awarię aplikacji, jeśli GetCurrentContext () zwróci nil.
Zrobiłbym zero sprawdzenia, czy oświadczenie:
class CustomView: UIView { override func draw(_ rect: CGRect) { super.draw(rect) if let context = UIGraphicsGetCurrentContext() { context.setStrokeColor(UIColor.gray.cgColor) context.setLineWidth(1) context.move(to: CGPoint(x: 0, y: bounds.height)) context.addLine(to: CGPoint(x: bounds.width, y: bounds.height)) context.strokePath() } } }
źródło
if
klauzuli jest po prostu rozpakowanie z opcjonalnego, wolęguard
zamiast tego użyć instrukcji.Dodaj etykietę bez tekstu iz kolorem tła odpowiadającym rozmiarowi ramki (np. Wysokość = 1). Zrób to za pomocą kodu lub w konstruktorze interfejsu.
źródło