Za pomocą następującego fragmentu kodu dodaję efekt cienia do jednego z moich UIView. Co działa całkiem nieźle. Ale gdy tylko ustawię właściwość masksToBounds widoku na TAK . Efekt cienia nie jest już renderowany.
self.myView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.myView.layer.shadowOpacity = 1.0;
self.myView.layer.shadowRadius = 10.0;
self.myView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
self.myView.layer.cornerRadius = 5.0;
self.myView.layer.masksToBounds = YES; // <-- This is causing the Drop shadow to not be rendered
UIBezierPath *path = [UIBezierPath bezierPathWithCurvedShadowForRect:self.myView.bounds];
self.myView.layer.shadowPath = path.CGPath;
self.myView.layer.shouldRasterize = YES;
Masz jakieś pomysły na ten temat?
ios
objective-c
uiview
calayer
jchatard
źródło
źródło
Teraz jest iOS 6, wszystko mogło się zmienić. Odpowiedź TheSquad nie działa dla mnie, dopóki nie udało mi się dodać jeszcze jednej linii
view2.layer.masksToBounds = NO;
, w przeciwnym razie cień się nie pojawi. Chociaż dokumentacja mówimasksToBounds
domyślnie jest NIE, mój kod pokazuje coś przeciwnego.Oto, jak tworzę przycisk w zaokrąglonym rogu z cieniem, który jest jednym z najczęściej używanych fragmentów kodu w mojej aplikacji.
button.layer.masksToBounds = YES; button.layer.cornerRadius = 10.0f; view.layer.masksToBounds = NO; // critical to add this line view.layer.cornerRadius = 10.0f; view.layer.shadowOpacity = 1.0f; // set shadow path to prevent horrible performance view.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:_button.bounds cornerRadius:10.0f].CGPath; [view addSubview:button];
EDYTOWAĆ
Jeśli widoki muszą być animowane lub przewijane,
masksToBounds = YES
wydajność podatkowa znacznie, co oznacza, że animacja prawdopodobnie będzie się zacinać. Aby uzyskać zaokrąglony narożnik i cień ORAZ płynną animację lub przewijanie, użyj następującego kodu:button.backgroundColor = [UIColor clearColor]; button.layer.backgroundColor = [UIColor redColor].CGColor; button.layer.masksToBounds = NO; button.layer.cornerRadius = 10.0f; view.layer.shadowOpacity = 0.5f; view.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:_button.bounds cornerRadius:10.0f].CGPath; view.layer.shadowOffset = CGSizeMake(0.0f, 4.0f); view.layer.shadowRadius = 2.0f; view.layer.masksToBounds = NO; view.layer.cornerRadius = 10.0f; [view addSubview:button];
źródło
To jest wersja odpowiedzi opublikowanej przez @TheSquad w wersjach Swift 3 i IBDesignable.
Użyłem tej samej koncepcji podczas wprowadzania zmian w pliku storyboardu. Najpierw przeniosłem swój targetView (ten, który wymaga promienia narożnika i cienia) do nowego containerView . Następnie dodałem następujące wiersze kodu (Odniesienie: https://stackoverflow.com/a/35372901/419192 ), aby dodać kilka atrybutów IBDesignable dla klasy UIView:
@IBDesignable extension UIView { /* The color of the shadow. Defaults to opaque black. Colors created * from patterns are currently NOT supported. Animatable. */ @IBInspectable var shadowColor: UIColor? { set { layer.shadowColor = newValue!.cgColor } get { if let color = layer.shadowColor { return UIColor(cgColor: color) } else { return nil } } } /* The opacity of the shadow. Defaults to 0. Specifying a value outside the * [0,1] range will give undefined results. Animatable. */ @IBInspectable var shadowOpacity: Float { set { layer.shadowOpacity = newValue } get { return layer.shadowOpacity } } /* The shadow offset. Defaults to (0, -3). Animatable. */ @IBInspectable var shadowOffset: CGPoint { set { layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y) } get { return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height) } } /* The blur radius used to create the shadow. Defaults to 3. Animatable. */ @IBInspectable var shadowRadius: CGFloat { set { layer.shadowRadius = newValue } get { return layer.shadowRadius } } /* The corner radius of the view. */ @IBInspectable var cornerRadius: CGFloat { set { layer.cornerRadius = newValue } get { return layer.cornerRadius } }
Po dodaniu tego kodu wróciłem do scenorysu i po wybraniu mojego containerView mogłem teraz znaleźć nowy zestaw atrybutów w inspektorze atrybutów:
Oprócz dodawania wartości dla tych atrybutów zgodnie z moim wyborem, dodałem również promień narożnika do mojego targetView i ustawiłem właściwość masksToBounds na true.
Mam nadzieję, że to pomoże :)
źródło
Wersja Swift 3.0 ze StoryBoard
Ten sam pomysł z @TheSquad. Utwórz nowy widok pod rzeczywistym widokiem i dodaj cień do dolnego widoku.
1. Utwórz widok pod rzeczywistym widokiem
Przeciągnij
UIView
do StoryBoard z tym samym ograniczeniem co widok docelowy. Zaznacz klip do powiązania dla widoku docelowego. Upewnij się również, że nowy widok jest wymieniony przed widokiem docelowym, tak aby widok docelowy obejmował nowy widok.2. Teraz połącz nowy widok z kodem, dodaj do niego cień
To tylko próbka. Tutaj możesz robić, co chcesz
shadowView.layer.masksToBounds = false shadowView.layer.shadowColor = UIColor.red.cgColor shadowView.layer.shadowOpacity = 0.5 shadowView.layer.shadowOffset = CGSize(width: -1, height: 1) shadowView.layer.shadowRadius = 3 shadowView.layer.shadowPath = UIBezierPath(rect: coverImage.bounds).cgPath shadowView.layer.shouldRasterize = true
źródło
Miałem też drastyczne problemy z wydajnością z cieniami i zaokrąglonymi rogami. Zamiast korzystać z części shadowPath, użyłem następujących linii, które doskonale rozwiązały problem wydajności:
self.layer.shouldRasterize = YES; self.layer.rasterizationScale = UIScreen.mainScreen.scale;
źródło
Oto jedno z rozwiązań:
@IBOutlet private weak var blockView: UIView! { didSet { blockView.backgroundColor = UIColor.white blockView.layer.shadowColor = UIColor.black.cgColor blockView.layer.shadowOpacity = 0.5 blockView.layer.shadowOffset = CGSize.zero blockView.layer.cornerRadius = 10 } } @IBOutlet private weak var imageView: UIImageView! { didSet { imageView.layer.cornerRadius = 10 imageView.layer.masksToBounds = true imageView.layer.shouldRasterize = true } }
źródło