Soweit ich weiß, können Sie die CALayer
Maskierung verwenden , wenn Sie auch die Unteransichten maskieren müssen. Es gibt zwei Möglichkeiten, dies zu tun. Der erste ist etwas eleganter, der zweite ist eine Problemumgehung :-) aber es ist auch schnell. Beide basieren auf CALayer
Maskierung. Ich habe beide Methoden letztes Jahr in einigen Projekten angewendet, dann hoffe ich, dass Sie etwas Nützliches finden können.
Lösung 1
Zunächst habe ich diese Funktion erstellt, um im laufenden Betrieb eine Bildmaske ( UIImage
) mit der abgerundeten Ecke zu erstellen, die ich benötige. Diese Funktion benötigt im Wesentlichen 5 Parameter: die Bildgrenzen und 4 Eckenradius (oben links, oben rechts, unten links und unten rechts).
static inline UIImage* MTDContextCreateRoundedMask( CGRect rect, CGFloat radius_tl, CGFloat radius_tr, CGFloat radius_bl, CGFloat radius_br ) {
CGContextRef context;
CGColorSpaceRef colorSpace;
colorSpace = CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate( NULL, rect.size.width, rect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast );
CGColorSpaceRelease(colorSpace);
if ( context == NULL ) {
return NULL;
}
CGFloat minx = CGRectGetMinX( rect ), midx = CGRectGetMidX( rect ), maxx = CGRectGetMaxX( rect );
CGFloat miny = CGRectGetMinY( rect ), midy = CGRectGetMidY( rect ), maxy = CGRectGetMaxY( rect );
CGContextBeginPath( context );
CGContextSetGrayFillColor( context, 1.0, 0.0 );
CGContextAddRect( context, rect );
CGContextClosePath( context );
CGContextDrawPath( context, kCGPathFill );
CGContextSetGrayFillColor( context, 1.0, 1.0 );
CGContextBeginPath( context );
CGContextMoveToPoint( context, minx, midy );
CGContextAddArcToPoint( context, minx, miny, midx, miny, radius_bl );
CGContextAddArcToPoint( context, maxx, miny, maxx, midy, radius_br );
CGContextAddArcToPoint( context, maxx, maxy, midx, maxy, radius_tr );
CGContextAddArcToPoint( context, minx, maxy, minx, midy, radius_tl );
CGContextClosePath( context );
CGContextDrawPath( context, kCGPathFill );
CGImageRef bitmapContext = CGBitmapContextCreateImage( context );
CGContextRelease( context );
UIImage *theImage = [UIImage imageWithCGImage:bitmapContext];
CGImageRelease(bitmapContext);
return theImage;
}
Jetzt brauchen Sie nur noch wenige Codezeilen. Ich habe Dinge in meine viewController- viewDidLoad
Methode eingefügt , weil sie schneller ist, aber Sie können sie auch in Ihrer benutzerdefinierten Methode UIView
mit der layoutSubviews
Methode im Beispiel verwenden.
- (void)viewDidLoad {
UIImage *mask = MTDContextCreateRoundedMask( self.view.bounds, 50.0, 50.0, 0.0, 0.0 );
CALayer *layerMask = [CALayer layer];
layerMask.frame = self.view.bounds;
layerMask.contents = (id)mask.CGImage;
self.view.layer.mask = layerMask;
self.view.backgroundColor = [UIColor redColor];
UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
testView.backgroundColor = [UIColor blueColor];
[self.view addSubview:testView];
[testView release];
[super viewDidLoad];
}
Lösung 2
Diese Lösung ist etwas "schmutziger". Im Wesentlichen können Sie eine Maskenebene mit der abgerundeten Ecke erstellen, die Sie benötigen (alle Ecken). Dann sollten Sie die Höhe der Maskenebene um den Wert des Eckenradius erhöhen. Auf diese Weise werden die unteren abgerundeten Ecken ausgeblendet und Sie können nur die obere abgerundete Ecke sehen. Ich habe den Code nur in die viewDidLoad
Methode eingefügt, weil er schneller ist, aber Sie können ihn auch in Ihrer benutzerdefinierten Methode UIView
mit der layoutSubviews
Methode im Beispiel verwenden.
- (void)viewDidLoad {
CGFloat radius = 50.0;
CGRect maskFrame = self.view.bounds;
maskFrame.size.height += radius;
CALayer *maskLayer = [CALayer layer];
maskLayer.cornerRadius = radius;
maskLayer.backgroundColor = [UIColor blackColor].CGColor;
maskLayer.frame = maskFrame;
self.view.layer.mask = maskLayer;
self.view.backgroundColor = [UIColor redColor];
UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
testView.backgroundColor = [UIColor blueColor];
[self.view addSubview:testView];
[testView release];
[super viewDidLoad];
}
Hoffe das hilft. Ciao!