UIViewで線を引く


86

UIViewで水平線を引く必要があります。それを行う最も簡単な方法は何ですか。たとえば、y-coord = 200で黒い水平線を描画したいとします。

私はInterfaceBuilderを使用していません。


1
これは、すべてのiOSで単一ピクセルの線を正しく持ち、ストーリーボードで簡単にするための完全で簡単なソリューションです:stackoverflow.com/a/26525466/294884
Fattie 2014年

回答:


122

あなたの場合(水平線)の最も簡単な方法は、黒い背景色とフレームでサブビューを追加すること[0, 200, 320, 1]です。

コードサンプル(エラーがないことを願っています-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...

もう1つの方法は、drawRectメソッドで線を描画するクラスを作成することです(これに関する私のコードサンプルはここにあります)。


Storyboardにコードを追加せずにこれを実行します。それはより簡単でより良いです。
coolcool1994 2017年

3
@ coolcool1994、「私はInterfaceBuilderを使用していません」に気づいていませんか。質問の要件?
Michael Kessler

312

これは少し遅いかもしれませんが、もっと良い方法があることを付け加えたいと思います。UIViewの使用は簡単ですが、比較的時間がかかります。このメソッドは、ビューがそれ自体を描画する方法をオーバーライドし、より高速になります。

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

このコードがUIViewで使用されている場合、このサンプルの座標は、ビューの境界または画面全体を基準にしていますか?
ChrisP 2011

CGContextBeginPath(context);前に電話する必要はありませんCGContextMoveToPoint(...);か?
i_am_jorf 2011年

37
ビューを使用してそれを行うことはそれほどひどいことではありません。たとえば、向きの変更中に暗黙的なアニメーションを実行する場合などに、作業が簡単になります。1つだけの場合、別のUIViewはそれほど高価ではなく、コードははるかに単純です。
i_am_jorf 2012

さらに、次のコードを使用して境界と中点を取得できます。CGPointmidPoint; midPoint.x = self.bounds.size.width / 2; midPoint.y = self.bounds.size.height / 2;
coolcool1994 2013

1
そうです、「遅い」というコメントは無意味です。画面にはいつでも膨大な数の単純なUIViewが表示されます。1つ(!)のテキスト文字を描画すると、それに伴うすべての処理で、塗りつぶされたUIViewを描画することになります。
Fattie 2014年

30

Swift3およびSwift4

これは、ビューの最後に灰色の線を引く方法です(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()
        }
    }
}

viewDidLayoutSubviewsから呼び出されると、「ifletcontext」は失敗します。
オスカー

14

テキストなしで背景色のラベルを追加するだけです。選択した座標と高さと幅を設定します。手動で、またはInterfaceBuilderを使用して実行できます。


11

これにはUIBezierPathクラスを使用できます。

そして、あなたが望むだけ多くの線を引くことができます:

私はUIViewをサブクラス化しました:

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

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

そして、線画に使用されるpathArrayオブジェクトとdictPAthオブジェクトを初期化しました。私は自分のプロジェクトからコードの主要部分を書いています:

- (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メソッド:

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

touchesMovedメソッド:

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メソッド:

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

11

もう1つの(そしてさらに短い)可能性。drawRect内にいる場合は、次のようになります。

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

0

GuyDaherの回答に基づいています。

使用を避けようとしていますか?GetCurrentContext()がnilを返すと、アプリケーションがクラッシュする可能性があるためです。

私はステートメントの場合はnilチェックを行います:

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
if句の理由がオプションからボックス化解除するだけの場合は、guard代わりにステートメントを使用することをお勧めします。
Julio Flores

-1

テキストなしで、フレームサイズに対応する背景色のラベルを追加します(例:高さ= 1)。コードを介して、またはインターフェイスビルダーでそれを行います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.