1

私はUIviewを作成し、次のようにマスクを適用しています。

baseView = [[ViewTutorialSubclass alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//self.view = baseView;
[self.view addSubview:baseView];
[baseView setBackgroundColor:[UIColor blackColor]];
baseView.userInteractionEnabled = YES;
baseView.alpha = 0.7;

mask = [[CAShapeLayer alloc] init];
mask.frame = baseView.layer.bounds;
CGRect biggerRect = CGRectMake(mask.frame.origin.x, mask.frame.origin.y, mask.frame.size.width, mask.frame.size.height);
CGRect smallerRect = CGRectMake(7.0f, 160.0f, 590.0f, 43.0f);

UIBezierPath *maskPath = [UIBezierPath bezierPath];
[maskPath moveToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMinY(biggerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMaxY(biggerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(biggerRect), CGRectGetMaxY(biggerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(biggerRect), CGRectGetMinY(biggerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMinY(biggerRect))];

[maskPath moveToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMinY(smallerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMaxY(smallerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(smallerRect), CGRectGetMaxY(smallerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(smallerRect), CGRectGetMinY(smallerRect))];
[maskPath addLineToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMinY(smallerRect))];

mask.path = maskPath.CGPath;
[mask setFillRule:kCAFillRuleEvenOdd];
mask.fillColor = [[UIColor blackColor] CGColor];
baseView.layer.mask = mask;

私のViewTutorialSubclass.mには次のものがあります。

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
for (UIView *v in self.subviews) {
    CGPoint localPoint = [v convertPoint:point fromView:self];
    if (v.alpha > 0.8 && [v pointInside:localPoint withEvent:event])
        return YES;
}
return NO;
}

アイデアは、ユーザーがマスク(非常に透明)でUIviewのいずれかの部分に触れた場合、すべてのユーザータッチがこの下のUIviewに渡され、ユーザーが他の場所に触れた場合、タッチはこの現在のUIviewに適用されるというものです。どうすればそれを着ることができますか?pointInsideは最良の解決策ですか?

4

1 に答える 1

3

マスクレイヤーを含むビューのクラスは、pointInsideをオーバーライドし、マスクの状態に基づいてYESまたはNOを返す必要があります。マスクが常に長方形になる場合は、長方形テストでポイントを実行できますが、それはあなたが望むものではないに違いありません。このテストを任意の形状のマスクで機能させる必要があります。(dispatch_onceで)1ピクセル幅のCGBitmapContextを設定します。pointInside:withEvent:マスクレイヤーをビットマップコンテキストにレンダリングし、何かが描画されたかどうかを確認します。次に例を示します。

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    static CGContextRef context;
    static CGColorSpaceRef rgbColorSpace;
    static unsigned char bitmapData[4];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        rgbColorSpace = CGColorSpaceCreateDeviceRGB();
        context = CGBitmapContextCreate(bitmapData, 1, 1, 8, 4, rgbColorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    });
    if ([super pointInside:point withEvent:event]) {
        CGContextTranslateCTM(context, -point.x, -point.y);
        [self.layer.mask renderInContext:context];
        CGContextTranslateCTM(context, point.x, point.y);
        BOOL result = (bitmapData[3] > 0);
        memset(bitmapData, 0, sizeof(bitmapData));
        return result;
    }
    return NO;
}

編集: xcode 5のコンパイラは、kCGImageAlphaPremultipliedLast(それ自体)をに渡すと、列挙型の不一致に関する警告を生成しますCGBitmapContextCreate。引数の型は想定されていますCGBitmapInfokCGImageAlphaPremultipliedLast、列挙型からのものCGImageAlphaInfoです。警告を削除するには、などの列挙型kCGImageAlphaPremultipliedLastの値と組み合わせることができます。新しいコードでは一般的な「ビットマップ情報」を送信することが明示されているため、とにかくこの方法の方が適していますが、アルファチャネルの処理方法に関連するビットマップ情報のみに関心があります。CGBitmapInfokCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast

于 2013-03-16T23:53:06.380 に答える