UIView'de çizgi çizin


86

Bir UIView'de yatay bir çizgi çizmem gerekiyor. Bunu yapmanın en kolay yolu nedir? Örneğin, y-coord = 200'de siyah bir yatay çizgi çizmek istiyorum.

Interface Builder'ı KULLANMIYORUM.


1
İşte tüm iOS'ta tek pikselli bir çizgiye doğru bir şekilde sahip olmanın ve bunu film şeridinde kolaylaştırmanın eksiksiz ve kolay çözümü: stackoverflow.com/a/26525466/294884
Fattie

Yanıtlar:


122

Sizin durumunuzda (yatay çizgi) en kolay yol, siyah arka plan rengi ve çerçevesi olan bir alt görünüm eklemektir [0, 200, 320, 1].

Kod örneği (umarım hata yoktur - Xcode olmadan yazdım):

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...

Başka bir yol da drawRect yönteminde bir çizgi çizecek bir sınıf oluşturmaktır (bunun için kod örneğimi burada görebilirsiniz ).


Bunu Storyboard'da herhangi bir kod olmadan yapın. Daha kolay ve daha iyi.
coolcool1994

3
@ coolcool1994, "Arayüz Oluşturucu kullanmıyorum" farkına varmadınız mı? sorudaki şart?
Michael Kessler

312

Belki biraz geç ama daha iyi bir yol olduğunu da eklemek istiyorum. UIView kullanmak basittir, ancak nispeten yavaştır. Bu yöntem, görünümün kendini nasıl çizdiğini geçersiz kılar ve daha hızlıdır:

- (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);
}

Bu kod bir UIV görünümünde kullanılıyorsa, bu örnekteki koordinatlar görünümün sınırlarına mı yoksa ekranın tamamına göre mi?
ChrisP

Daha CGContextBeginPath(context);önce aramana gerek yok CGContextMoveToPoint(...);mu?
i_am_jorf

37
Bunu yapmak için bir manzara kullanmak çok da korkunç değil. Örneğin, oryantasyon değişiklikleri sırasında örtük animasyonlar yaparken işleri kolaylaştırır. Sadece biriyse, başka bir UIView o kadar pahalı değildir ve kod çok daha basittir.
i_am_jorf

Ayrıca şu kodlarla sınırlar ve orta nokta elde edebilirsiniz: CGPoint midPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994

1
Doğru, "yavaş" olduğu yorumu mantıklı değil. Herhangi bir zamanda ekranda çok sayıda basit UIVView vardır. Bir (!) Metin karakteri çizmenin, içerdiği tüm işlemlerle dolu bir UIView çizdiğini unutmayın.
Şişko

30

Swift 3 ve Swift 4

Görüşünüzün sonunda gri bir çizgi nasıl çizebilirsiniz (b123400'ün cevabı ile aynı fikir)

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()
        }
    }
}

ViewDidLayoutSubviews'den çağrıldığında "if let bağlamı" başarısız olur.
Oscar

14

Metinsiz ve arka plan rengiyle bir Etiket eklemeniz yeterlidir. İstediğiniz Koordinatları ve ayrıca yüksekliği ve genişliği ayarlayın. Manuel olarak veya Interface Builder ile yapabilirsiniz.


11

Bunun için UIBezierPath Sınıfını kullanabilirsiniz:

Ve istediğiniz kadar çizgi çizebilirsiniz:

UIView alt sınıfına girdim:

    @interface MyLineDrawingView()
    {
       NSMutableArray *pathArray;
       NSMutableDictionary *dict_path;
       CGPoint startPoint, endPoint;
    }

       @property (nonatomic,retain)   UIBezierPath *myPath;
    @end

Ve çizgi çizme için kullanılacak pathArray ve dictPAth nesnelerini başlattı. Kodun ana bölümünü kendi projemden yazıyorum:

- (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];

}

touchesBegin yöntemi:

UITouch *touch = [touches anyObject];
startPoint = [touch locationInView:self];
myPath=[[UIBezierPath alloc]init];
myPath.lineWidth = currentSliderValue*2;
dict_path = [[NSMutableDictionary alloc] init];

touchesMoved Yöntemi:

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];

touchesEnded Yöntemi:

        NSDictionary *tempDict = [NSDictionary dictionaryWithDictionary:dict_path];
        [pathArray addObject:tempDict];
        [dict_path removeAllObjects];
        [self setNeedsDisplay];

11

Bir başka (ve daha da kısa) olasılık. DrawRect içindeyseniz, aşağıdakine benzer bir şey:

[[UIColor blackColor] setFill];
UIRectFill((CGRect){0,200,rect.size.width,1});

0

Guy Daher'in cevabına göre.

Kullanmaktan kaçınmaya mı çalışıyorum? çünkü GetCurrentContext () nil değerini döndürürse uygulamanın çökmesine neden olabilir.

İfadeyi kontrol etmezdim:

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()
        }
    }
}

2
ifcümlenin nedeni yalnızca isteğe bağlı olanın kutusunu kaldırmaksa, guardbunun yerine bir ifade kullanmayı tercih edin .
Julio Flores

-1

Metinsiz ve arka plan rengine karşılık gelen çerçeve boyutuyla etiket ekleyin (ör: yükseklik = 1). Bunu kod aracılığıyla veya arayüz oluşturucuda yapın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.