3

すべてのコンテキストを再描画せずにビューに線を描画する方法を見つけようとしています。

これが私の描画方法です:

-(void)drawInContext:(CGContextRef)context {
    for (int i = 0; i < self.drawings.count; ++i) {
        Drawing* drawing = [self.drawings objectAtIndex:i];

        CGContextSetStrokeColorWithColor(context, drawing.colorTrait.CGColor);
        CGContextSetLineWidth(context, 1.0);

        CGContextMoveToPoint(context, [[drawing.points objectAtIndex:0] CGPointValue].x * self.zoomScale, [[drawing.points objectAtIndex:] CGPointValue].y * self.zoomScale);

        for (int i = 1; i < drawing.points.count; i++) {
            CGContextAddLineToPoint(context, [[drawing.points objectAtIndex:i] CGPointValue].x * self.zoomScale, [[drawing.points objectAtIndex:i] CGPointValue].y * self.zoomScale);
        }

        CGContextStrokePath(context);
    }
}

-(void)drawRect:(CGRect)rect {
    if (isRedrawing) {
        [self drawInContext:UIGraphicsGetCurrentContext()];
        isRedrawing = NO;
    }

    [[UIColor redColor] set];
    [currentPath stroke];
}

しかし、touches メソッドで setNeedsDisplay を呼び出すと、ビューが完全にクリアされます。私のメソッドを機能させる方法はありますか?

4

1 に答える 1

3

良くも悪くも、レイヤーを使用します。

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (first) {

        // Wait for the first call to get a valid context

        first = NO;

        // Then create a CGContextRef (offlineContext_1) and matching CGLayer (layer_1)

        layer_1 = CGLayerCreateWithContext (context,self.bounds.size, NULL);    
        offlineContext_1 = CGLayerGetContext (layer_1);

        // If you have any pending graphics to draw, draw them now on offlineContext_1

    }

    // Normally graphics calls are made here, but the use of an "offline" context means the graphics calls can be made any time.

    CGContextSaveGState(context);

    // Write whatever is in offlineContext_1 to the UIView's context 

    CGContextDrawLayerAtPoint (context, CGPointZero, layer_1);
    CGContextRestoreGState(context);

}

UIView のコンテキストは常にクリアされますが、レイヤーに関連付けられたオフライン コンテキストはクリアされません。グラフィック アクションを蓄積し続けることができ、drawRect によってクリアされることはありません。

編集:あなたの問題と私が解決した問題との違いを指摘しました。最初の表示の前に何かを描きたいのに対し、最初の表示の後まで何も描く必要はありませんでした。私の記憶では、いつでも任意のサイズと解像度でレイヤーを作成できます。有効なコンテキスト (現在のデバイスに適した設定) が渡されるのを待ってから、そのコンテキストに基づいて新しいコンテキスト/レイヤーを作成するのが最も簡単であることがわかりました。「if (first)」ブロックの内部を参照してください。

同じことを行うことができますが、最初の drawRect: が呼び出されるまで、サーバーから取得した行などもキャッシュする必要があります。次に、指定されたコンテキストでオフライン コンテキストを作成し、サーバーから取得した線などをオフライン コンテキストに描画してから、以下に示すようにレイヤーを描画します。したがって、メソッドに追加する唯一のことは、続行する前に保留中のサーバー ソース グラフィックスを描画するための "if (first)" ループ内での呼び出しです (ソースに追加されたコメントを参照してください)。

于 2012-12-11T23:08:09.793 に答える