2

私の目的は、穴として表示されるはずの空の丸いボックスを UIView に描画して、下にあるものを表示することです。以下に示すように、 drawRect メソッドをオーバーライドしてこれを作成しました。これにより、holeRect プロパティ (CGRect) のサイズの丸みを帯びた四角形を作成し、内部の影をそこにドロップしてビューに配置し、( clearColorおよびCGContextSetBlendMode(context, kCGBlendModeSourceOut)を使用して) クリアすることができます。このボックスでカバーされ、私のビューの背後にあるものを明らかにする領域 (この質問からいくつかのコードを取得して変更しました)。今私の問題は、アニメーションでこの四角形を移動してサイズを変更する必要があることです。その方法が見つかりません。これを行うには間違った方法を選択している可能性がありますが、描画の専門家ではないので、ヒント非常に高く評価されます。

- (void)drawRect:(CGRect)rect
{



//I set the frame of my "holey" rect
CGRect bounds =  self.holeRect;
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat radius = 20;

//fill my whole view with gray
CGContextSetFillColorWithColor( context, [UIColor colorWithRed:.5 green:.5 blue:.5 alpha:.8].CGColor );
CGContextFillRect( context, rect );

// Create the "visible" path, which will be the shape that gets the inner shadow
// In this case it's just a rounded rect, but could be as complex as your want
CGMutablePathRef visiblePath = CGPathCreateMutable();
CGRect innerRect = CGRectInset(bounds, radius, radius);
CGPathMoveToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x + innerRect.size.width, bounds.origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, bounds.origin.y, bounds.origin.x + bounds.size.width, innerRect.origin.y, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, innerRect.origin.y + innerRect.size.height);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height, innerRect.origin.x + innerRect.size.width, bounds.origin.y + bounds.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y + bounds.size.height);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x, bounds.origin.y + bounds.size.height, bounds.origin.x, innerRect.origin.y + innerRect.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x, innerRect.origin.y);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x, bounds.origin.y, innerRect.origin.x, bounds.origin.y, radius);
CGPathCloseSubpath(visiblePath);

// Fill this path
UIColor *aColor = [UIColor clearColor];
[aColor setFill];
CGContextAddPath(context, visiblePath);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextFillPath(context);


// Now create a larger rectangle, which we're going to subtract the visible path from
// and apply a shadow
CGMutablePathRef path = CGPathCreateMutable();
//(when drawing the shadow for a path whichs bounding box is not known pass "CGPathGetPathBoundingBox(visiblePath)" instead of "bounds" in the following line:)
//-42 cuould just be any offset > 0
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));

// Add the visible path (so that it gets subtracted for the shadow)
CGPathAddPath(path, NULL, visiblePath);
CGPathCloseSubpath(path);

// Add the visible paths as the clipping path to the context
CGContextAddPath(context, visiblePath);
CGContextClip(context);


// Now setup the shadow properties on the context
aColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 5.0f, [aColor CGColor]);

// Now fill the rectangle, so the shadow gets drawn
[aColor setFill];   
CGContextSaveGState(context);   
CGContextAddPath(context, path);
CGContextEOFillPath(context);

// Release the paths
//CGPathRelease(path);
CGPathRelease(visiblePath);

}
4

2 に答える 2

1

UIImageView に穴を開けることについての質問に対して私が行ったこの回答を見てください。

https://stackoverflow.com/a/8632731/341994

それが機能する方法は、UIImageView のスーパービューのレイヤーに、マスキングを実行して穴を開けるサブレイヤーがあることに注意してください。つまり、穴をアニメートするには、そのサブレイヤーの動きをアニメートするだけです。私の本で説明されているように、それは Core Animation では簡単です。

http://www.apeth.com/iOSBook/ch17.html#_using_a_cabasicanimation

言い換えれば、実行していることすべてをレイヤーとしてカプセル化できれば、レイヤーを移動してアニメーション化することは簡単です。

于 2013-04-09T02:08:27.830 に答える
0

すでに行っている設定に従って、カットアウトの位置をビュー クラス (このdrawRectメソッドを実装するクラス) のインスタンス変数に格納し、NSTimer を使用して位置を定期的に更新します。たとえば、ビューのコードでは、次のようにスケジュールされたタイマーを作成できます。

[NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:self selector:@selector(updateCutoutPosition) userInfo:nil repeats:YES];

次に update メソッドを実装します。

- (void)updateCutoutPosition {
    // Do whatever you need to do to update the position of the cutout.
    [self setNeedsDisplay]; // Will cause drawRect to be called again soon.
}
于 2013-04-09T01:59:31.727 に答える