Tarik garis di UIView

86

Saya perlu menggambar garis horizontal di UIView. Apa cara termudah untuk melakukannya. Misalnya, saya ingin menggambar garis horizontal hitam pada y-coord = 200.

Saya TIDAK menggunakan Interface Builder.

John Smith
sumber
1
Berikut adalah solusi lengkap & mudah untuk memiliki garis piksel tunggal dengan benar, di semua iOS, dan membuatnya mudah di storyboard: stackoverflow.com/a/26525466/294884
Fattie

Jawaban:

122

Cara termudah dalam kasus Anda (garis horizontal) adalah menambahkan subview dengan warna latar belakang hitam dan bingkai [0, 200, 320, 1].

Contoh kode (Saya harap tidak ada kesalahan - Saya menulisnya tanpa 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...

Cara lain adalah membuat kelas yang akan menggambar garis dalam metode drawRect (Anda dapat melihat contoh kode saya untuk ini di sini ).

Michael Kessler
sumber
Lakukan ini tanpa kode apa pun di Storyboard. Lebih mudah dan lebih baik.
coolcool1994
3
@ coolcool1994, pernahkah Anda memperhatikan "Saya TIDAK menggunakan Interface Builder." persyaratan dalam pertanyaan?
Michael Kessler
312

Mungkin ini agak terlambat, tapi saya ingin menambahkan bahwa ada cara yang lebih baik. Menggunakan UIView sederhana, tetapi relatif lambat. Metode ini menimpa cara menggambar dirinya sendiri dan lebih cepat:

- (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);
}
b123400
sumber
Jika kode ini digunakan dalam UIView, apakah koordinat dalam sampel ini relatif terhadap batas tampilan atau seluruh layar?
ChrisP
Apakah seseorang tidak perlu menelepon CGContextBeginPath(context);sebelumnya CGContextMoveToPoint(...);?
i_am_jorf
37
Menggunakan pandangan untuk melakukannya tidak terlalu buruk. Itu membuat segalanya lebih mudah, misalnya, saat melakukan animasi implisit selama perubahan orientasi. Jika hanya satu, UIView lain tidak terlalu mahal dan kodenya jauh lebih sederhana.
i_am_jorf
Selain itu, Anda bisa mendapatkan batas dan titik tengah dengan kode ini: CGPoint midpoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994
1
Benar, komentar bahwa itu "lambat" tidak masuk akal. Ada banyak UIViews sederhana di layar setiap saat. Perhatikan bahwa menggambar karakter teks SATU (!), Dengan semua proses yang terlibat, rawa menggambar UIView yang terisi.
Fattie
30

Swift 3 dan Swift 4

Ini adalah bagaimana Anda bisa menggambar garis abu-abu di akhir tampilan Anda (ide yang sama seperti jawaban 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()
        }
    }
}
Guy Daher
sumber
"Jika biarkan konteks" gagal saat dipanggil dari viewDidLayoutSubviews.
Oscar
14

Cukup tambahkan Label tanpa teks dan dengan warna latar belakang. Atur Koordinat pilihan Anda dan juga tinggi dan lebar. Anda dapat melakukannya secara manual atau dengan Interface Builder.

Phanindra
sumber
11

Anda dapat menggunakan UIBezierPath Class untuk ini:

Dan dapat menggambar garis sebanyak yang Anda inginkan:

Saya telah membuat subclass UIView:

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

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

Dan menginisialisasi objek pathArray dan dictPAth yang akan digunakan untuk menggambar garis. Saya menulis bagian utama kode dari proyek saya sendiri:

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

}

metode touchesBegin:

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

touchesMoved Method:

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

Metode touchesEnded:

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

Satu kemungkinan lainnya (dan bahkan lebih pendek). Jika Anda berada di dalam drawRect, seperti berikut ini:

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

Berdasarkan jawaban Guy Daher.

Saya mencoba untuk menghindari penggunaan? karena bisa menyebabkan aplikasi macet jika GetCurrentContext () mengembalikan nihil.

Saya tidak akan memeriksa jika pernyataan:

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()
        }
    }
}
Robert Harrold
sumber
2
jika alasan ifklausa hanya untuk melepas kotak dari opsional, lebih baik gunakan guardpernyataan sebagai gantinya.
Julio Flores
-1

Tambahkan label tanpa teks dan dengan warna latar belakang sesuai ukuran frame (misal: tinggi = 1). Lakukan melalui kode atau di pembuat antarmuka.

Reddy
sumber