Dla każdego, kto zastanawia się, jak narysować wewnętrzny cień za pomocą Core Graphics zgodnie z sugestią Costique, oto jak: (na iOS dostosuj w razie potrzeby)
W twoim drawRect: metoda ...
CGRect bounds = [self bounds];
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat radius = 0.5f * CGRectGetHeight(bounds);
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);
UIColor *aColor = [UIColor redColor];
[aColor setFill];
CGContextAddPath(context, visiblePath);
CGContextFillPath(context);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));
CGPathAddPath(path, NULL, visiblePath);
CGPathCloseSubpath(path);
CGContextAddPath(context, visiblePath);
CGContextClip(context);
aColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 3.0f, [aColor CGColor]);
[aColor setFill];
CGContextSaveGState(context);
CGContextAddPath(context, path);
CGContextEOFillPath(context);
CGPathRelease(path);
CGPathRelease(visiblePath);
Tak więc zasadniczo są następujące kroki:
- Stwórz swoją ścieżkę
- Ustaw żądany kolor wypełnienia, dodaj tę ścieżkę do kontekstu i wypełnij kontekst
- Teraz utwórz większy prostokąt, który może wiązać widoczną ścieżkę. Przed zamknięciem tej ścieżki dodaj widoczną ścieżkę. Następnie zamknij ścieżkę, aby utworzyć kształt z odjętą widoczną ścieżką. Możesz chcieć zbadać metody wypełniania (niezerowe nawijanie parzystych / nieparzystych) w zależności od tego, jak utworzyłeś te ścieżki. Zasadniczo, aby ścieżki podrzędne „odejmowały” po dodaniu ich do siebie, należy je narysować (a raczej skonstruować) w przeciwnych kierunkach, jedną zgodnie z ruchem wskazówek zegara, a drugą przeciwnie do ruchu wskazówek zegara.
- Następnie musisz ustawić widoczną ścieżkę jako ścieżkę przycinającą w kontekście, aby nie rysować niczego poza nią na ekranie.
- Następnie ustaw cień w kontekście, który obejmuje przesunięcie, rozmycie i kolor.
- Następnie wypełnij duży kształt otworem w nim. Kolor nie ma znaczenia, ponieważ jeśli zrobiłeś wszystko dobrze, nie zobaczysz tego koloru, tylko cień.