Özel bir UIView
... istiyorum : Sadece yuvarlatılmış köşeleri ve açık gölge (ışık efekti olmadan) ile boş bir beyaz görünüm istedim. Bunların her birini tek tek yapabilirim ama olağan clipToBounds
/ maskToBounds
çatışmalar meydana gelir.
Özel bir UIView
... istiyorum : Sadece yuvarlatılmış köşeleri ve açık gölge (ışık efekti olmadan) ile boş bir beyaz görünüm istedim. Bunların her birini tek tek yapabilirim ama olağan clipToBounds
/ maskToBounds
çatışmalar meydana gelir.
Yanıtlar:
Aşağıdaki kod parçası kenarlık, sınır yarıçapı ve gölge ekler v
bir UIView
:
// border radius
[v.layer setCornerRadius:30.0f];
// border
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];
// drop shadow
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];
Ayarları ihtiyaçlarınıza göre ayarlayabilirsiniz.
Ayrıca, projenize QuartzCore çerçevesini ekleyin ve:
#import <QuartzCore/QuartzCore.h>
İle ilgili diğer cevabımı görün masksToBounds
.
Not
Bu her durumda çalışmayabilir. Bu yöntemin gerçekleştirdiğiniz diğer çizim işlemlerine müdahale ettiğini fark ederseniz, lütfen bu cevaba bakın .
// corner radius
blueView.layer.cornerRadius = 10
// border
blueView.layer.borderWidth = 1.0
blueView.layer.borderColor = UIColor.black.cgColor
// shadow
blueView.layer.shadowColor = UIColor.black.cgColor
blueView.layer.shadowOffset = CGSize(width: 3, height: 3)
blueView.layer.shadowOpacity = 0.7
blueView.layer.shadowRadius = 4.0
İçeriğini görüşümüzün sınırlarına kırpmak istediğimiz alt katmanlar veya alt görünümler (resim gibi) varsa ne olur?
Bunu şu şekilde yapabiliriz:
blueView.layer.masksToBounds = true
(Alternatif olarak, aynı sonucublueView.clipsToBounds = true
verir .)
Ama, hayır! Gölge de kesildi çünkü sınırların dışında! Ne yapalım? Ne yapalım?
Çözüm
Gölge ve kenarlık için ayrı görünümler kullanın. Taban görünümü saydamdır ve gölgeye sahiptir. Sınır görünümü, sınırlarına sahip olduğu diğer alt içerikleri de kırpar.
// add the shadow to the base view
baseView.backgroundColor = UIColor.clear
baseView.layer.shadowColor = UIColor.black.cgColor
baseView.layer.shadowOffset = CGSize(width: 3, height: 3)
baseView.layer.shadowOpacity = 0.7
baseView.layer.shadowRadius = 4.0
// add the border to subview
let borderView = UIView()
borderView.frame = baseView.bounds
borderView.layer.cornerRadius = 10
borderView.layer.borderColor = UIColor.black.cgColor
borderView.layer.borderWidth = 1.0
borderView.layer.masksToBounds = true
baseView.addSubview(borderView)
// add any other subcontent that you want clipped
let otherSubContent = UIImageView()
otherSubContent.image = UIImage(named: "lion")
otherSubContent.frame = borderView.bounds
borderView.addSubview(otherSubContent)
Bu, aşağıdaki sonucu verir:
Yuvarlak köşeler ve gölgeler eklemek bir performans isabeti olabilir. Gölge için önceden tanımlanmış bir yol kullanarak ve ayrıca rasterleştirileceğini belirterek performansı artırabilirsiniz. Aşağıdaki kod yukarıdaki örneğe eklenebilir.
baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale
Daha fazla ayrıntı için bu gönderiye bakın. Buraya ve buraya da bakın .
Bu cevap Swift 4 ve Xcode 9 ile test edildi.
baseView.backgroundColor = UIColor.clear
gölgeyi kaldırır. Yalnızca bir arka plan rengi ayarladıysanız görürsünüz.
Bunu yapmanın bir yolu, köşeleri yuvarlatılmış görünümü alt gölge ile görünüm haline getirmektir.
UIView* roundedView = [[UIView alloc] initWithFrame: frame];
roundedView.layer.cornerRadius = 5.0;
roundedView.layer.masksToBounds = YES;
UIView* shadowView = [[UIView alloc] initWithFrame: frame];
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowRadius = 5.0;
shadowView.layer.shadowOffset = CGSizeMake(3.0, 3.0);
shadowView.layer.shadowOpacity = 1.0;
[shadowView addSubview: roundedView];
Ardından, shadowView'ı istediğiniz yere ekleyebilirsiniz.
Bileşeni doğru kullandığınızdan emin olmak için GitHub'daki örnek projeye göz atın .
Ek alt görünüm veya alt sınıflama olmadan basit Swift 5 çözümü:
extension UIView {
func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
layer.masksToBounds = false
layer.shadowOffset = offset
layer.shadowColor = color.cgColor
layer.shadowRadius = radius
layer.shadowOpacity = opacity
let backgroundCGColor = backgroundColor?.cgColor
backgroundColor = nil
layer.backgroundColor = backgroundCGColor
}
}
Aramadan önce görünümünüzü köşe yarıçapı ve diğer özelliklerle ayarlamanız gerektiğini unutmayın addShadow
.
Bundan sonra, bunu şu şekilde arayın viewDidLoad
:
button.addShadow(offset: CGSize.init(width: 0, height: 3), color: UIColor.black, radius: 2.0, opacity: 0.35)
Son sonuç:
Süper kolay ve basit!
layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath
. Neden olduğunu açıklayamıyorum, birisinin bunun için bir açıklaması var mı?
Bu benim için çalıştı. Hile, arka plan rengini ana görünümden katmana taşımaktı.
CALayer *layer = view.layer;
layer.cornerRadius = 15.0f;
layer.masksToBounds = NO;
layer.shadowOffset = CGSizeMake(0, 3);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 2.0f;
layer.shadowOpacity = 0.35f;
layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:layer.cornerRadius] CGPath];
CGColorRef bColor = view.backgroundColor.CGColor;
view.backgroundColor = nil;
layer.backgroundColor = bColor ;
UIView extension
Burada kullanarak yanıtınızın Swift 3.1 sürümünü oluşturdum - stackoverflow.com/a/43295741/1313939 İlhamınız için teşekkürler!
Kapsayıcı görünümü için gölge yolu atarken aşağıdaki hileyi kullanarak sorunu çözdüm:
[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]
Gölgeye verilen yolun, hücrenin içerdiği arka planla aynı köşe yarıçapına sahip yuvarlak bir dikdörtgen olduğuna dikkat edin:
//this is the border for the UIView that is added to a cell
cell.backgroundView.layer.cornerRadius = 12;
cell.backgroundView.layer.masksToBounds = YES;
cell.backgroundView.layer.borderColor = [UIColor darkGrayColor].CGColor;
cell.backgroundView.layer.borderWidth = 1;
//this is the shadow around the cell itself (cannot have round corners with borders and shadow, need to use two views
cell.layer.shadowRadius = 2;
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = NO;
[[cell layer] setShadowColor:[[UIColor darkGrayColor] CGColor]];
[[cell layer] setShadowOffset:CGSizeMake(0.0,0.0)];
[[cell layer] setShadowOpacity:1.0];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12];
[[cell layer] setShadowPath:[path CGPath]];
Eğer yuvarlanmış corners
vs.'ye subviews
karşı mücadele ediyorsanız masksToBounds
, benim fonksiyonumu kullanmayı deneyin:
- (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
CGRect shadowFrame; // Modify this if needed
shadowFrame.size.width = 0.f;
shadowFrame.size.height = 0.f;
shadowFrame.origin.x = 0.f;
shadowFrame.origin.y = 0.f;
UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
shadow.userInteractionEnabled = NO; // Modify this if needed
shadow.layer.shadowColor = color.CGColor;
shadow.layer.shadowOffset = shadowOffset;
shadow.layer.shadowRadius = shadowRadius;
shadow.layer.masksToBounds = NO;
shadow.clipsToBounds = NO;
shadow.layer.shadowOpacity = shadowOpacity;
[view.superview insertSubview:shadow belowSubview:view];
[shadow addSubview:view];
return shadow;
}
görünümünüzde arayın. görünümünüzün köşeleri yuvarlanmış olsun, boyutu ne olursa olsun, şekli - hoş bir gölge çizilecek.
Tablonun kaldırılmasını istediğinizde başvurabilmeniz için işlevin dönüş değerini korumanız yeterlidir (veya örneğin kullanın insertSubview:aboveView:
)
shadow.userInteractionEnabled = NO; // Modify this if needed
? Yani ihtiyaç duyulan durum budur. userInteractionEnabled
zaten aşina olmanız gereken temel ve popüler bir özelliktir :-)
Swift 4 ve Xcode 9'u kullanarak , bir alt ImageView
gölge ve bir kenarlık içeren bir yuvarlama için çalışan bir örnektir .
//set dimensions and position of image (in this case, centered)
let imageHeight: CGFloat = 150, imageWidth: CGFloat = 150
let xPosition = (self.view.frame.width / 2) - (imageWidth / 2)
let yPosition = (self.view.frame.height / 2) - (imageHeight / 2)
//set desired corner radius
let cornerRadius: CGFloat = 20
//create container for the image
let imageContainer = UIView(frame: CGRect(x: xPosition, y: yPosition, width: imageWidth, height: imageHeight))
//configure the container
imageContainer.clipsToBounds = false
imageContainer.layer.shadowColor = UIColor.black.cgColor
imageContainer.layer.shadowOpacity = 1
imageContainer.layer.shadowOffset = CGSize(width: 3.0, height: 3.0)
imageContainer.layer.shadowRadius = 5
imageContainer.layer.shadowPath = UIBezierPath(roundedRect: imageContainer.bounds, cornerRadius: cornerRadius).cgPath
//create imageView
let imageView = UIImageView(frame: imageContainer.bounds)
//configure the imageView
imageView.clipsToBounds = true
imageView.layer.cornerRadius = cornerRadius
//add a border (if required)
imageView.layer.borderColor = UIColor.black.cgColor
imageView.layer.borderWidth = 1.0
//set the image
imageView.image = UIImage(named: "bird")
//add the views to the superview
view.addSubview(imageContainer)
imageContainer.addSubview(imageView)
Görüntünün dairesel olmasını istiyorsanız: (ve kenarlıksız olarak gösterilir)
let cornerRadius = imageWidth / 2
UIView'da bir yardımcı oluşturdum
@interface UIView (Helper)
- (void)roundCornerswithRadius:(float)cornerRadius
andShadowOffset:(float)shadowOffset;
@end
buna böyle diyebilirsin
[self.view roundCornerswithRadius:5 andShadowOffset:5];
İşte uygulama
- (void)roundCornerswithRadius:(float)cornerRadius
andShadowOffset:(float)shadowOffset
{
const float CORNER_RADIUS = cornerRadius;
const float SHADOW_OFFSET = shadowOffset;
const float SHADOW_OPACITY = 0.5;
const float SHADOW_RADIUS = 3.0;
UIView *superView = self.superview;
CGRect oldBackgroundFrame = self.frame;
[self removeFromSuperview];
CGRect frameForShadowView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
UIView *shadowView = [[UIView alloc] initWithFrame:frameForShadowView];
[shadowView.layer setShadowOpacity:SHADOW_OPACITY];
[shadowView.layer setShadowRadius:SHADOW_RADIUS];
[shadowView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];
[self.layer setCornerRadius:CORNER_RADIUS];
[self.layer setMasksToBounds:YES];
[shadowView addSubview:self];
[superView addSubview:shadowView];
}
Yuvarlak köşe görünümünün gölge ile bir günlük bir araştırmasından sonra, özel uiview sınıfımı buraya göndermekten memnuniyet duyuyorum, bu soruyu bitirmeyi umuyoruz:
#import <UIKit/UIKit.h>
@interface RoundCornerShadowView : UIView
@end
#import "RoundCornerShadowView.h"
@implementation RoundCornerShadowView
// *** must override this method, not the other method ***
// otherwise, the background corner doesn't disappear....
// @2015/05/29
-(void) layoutSubviews {
[super layoutSubviews];//is must to ensure rightly layout children view
//1. first, create Inner layer with content
CALayer *innerView = [CALayer layer];
innerView.frame = CGRectMake(0,0,self.bounds.size.width,self.bounds.size.height);
//instead of: innerView.frame = self.frame;
innerView.borderWidth = 1.0f;
innerView.cornerRadius = 6.0f;
innerView.masksToBounds = YES;
innerView.borderColor = [[UIColor lightGrayColor] CGColor];
innerView.backgroundColor = [[UIColor whiteColor] CGColor];
//put the layer to the BOTTOM of layers is also a MUST step...
//otherwise this layer will overlay the sub uiviews in current uiview...
[self.layer insertSublayer:innerView atIndex:0];
//2. then, create shadow with self layer
self.layer.masksToBounds = NO;
self.layer.shadowColor = [[UIColor darkGrayColor] CGColor];
self.layer.shadowOpacity = 0.4f;
//shadow length
self.layer.shadowRadius = 2.0f;
//no offset
self.layer.shadowOffset = CGSizeMake(0, 0);
//right down shadow
//[self.layer setShadowOffset: CGSizeMake(1.0f, 1.0f)];
//3. last but important, MUST clear current view background color, or the color will show in the corner!
self.backgroundColor = [UIColor clearColor];
}
@end
Bu nedenle, hedef görünümde alt veya üst görünüm eklemenize gerek yok, sadece geçerli görünümde bir katman ekleyin ve tamamlamak için 3 adım yapın!
koddaki yorumlara yakından bakın, bileşeni anlamak yardımcı olur!
Hızlı 4'te test edilen bir şey
import UIKit
extension UIView {
@IBInspectable var dropShadow: Bool {
set{
if newValue {
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.4
layer.shadowRadius = 1
layer.shadowOffset = CGSize.zero
} else {
layer.shadowColor = UIColor.clear.cgColor
layer.shadowOpacity = 0
layer.shadowRadius = 0
layer.shadowOffset = CGSize.zero
}
}
get {
return layer.shadowOpacity > 0
}
}
}
üretir
Müfettiş'te şu şekilde etkinleştirirseniz:
Kullanıcı Tanımlı Çalışma Zamanı Özelliğini ekler ve bunun sonucunda:
(Daha önce ekledim cornerRadius = 8
)
:)
Kullanımı shadowView
veroundView
shadowView
roundView
shadowView
içeride bir düzen oluşturmak ve gölgesinin parlaması gerekiyor. Arkada tamamen görünmeyecek insets
şekilde ayarlayınshadowView
roundView
Roundview
Kod
addSubviews(shadowView, roundView)
roundView.addSubviews(titleLabel, subtitleLabel, imageView)
// need inset
shadowView.pinEdges(view: self, inset: UIEdgeInsets(constraintInsets: 2))
roundView.pinEdges(view: self)
do {
shadowView.backgroundColor = .white // need background
let layer = shadowView.layer
layer.shadowColor = UIColor.black.cgColor
layer.shadowRadius = 3
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.7
layer.shouldRasterize = true
}
do {
roundView.backgroundColor = .white
let layer = roundView.layer
layer.masksToBounds = true
layer.cornerRadius = 5
}
Veya aşağıda belirtmeden yapabilirsiniz clipToBounds/maskToBounds
layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.8
Swift 3 ve IBI öngörülebilir çözüm: Ade'nin çözümünden
ilham aldı
İlk olarak, bir UIView uzantısı oluşturun:
//
// UIView-Extension.swift
//
import Foundation
import UIKit
@IBDesignable
extension UIView {
// Shadow
@IBInspectable var shadow: Bool {
get {
return layer.shadowOpacity > 0.0
}
set {
if newValue == true {
self.addShadow()
}
}
}
fileprivate func addShadow(shadowColor: CGColor = UIColor.black.cgColor, shadowOffset: CGSize = CGSize(width: 3.0, height: 3.0), shadowOpacity: Float = 0.35, shadowRadius: CGFloat = 5.0) {
let layer = self.layer
layer.masksToBounds = false
layer.shadowColor = shadowColor
layer.shadowOffset = shadowOffset
layer.shadowRadius = shadowRadius
layer.shadowOpacity = shadowOpacity
layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath
let backgroundColor = self.backgroundColor?.cgColor
self.backgroundColor = nil
layer.backgroundColor = backgroundColor
}
// Corner radius
@IBInspectable var circle: Bool {
get {
return layer.cornerRadius == self.bounds.width*0.5
}
set {
if newValue == true {
self.cornerRadius = self.bounds.width*0.5
}
}
}
@IBInspectable var cornerRadius: CGFloat {
get {
return self.layer.cornerRadius
}
set {
self.layer.cornerRadius = newValue
}
}
// Borders
// Border width
@IBInspectable
public var borderWidth: CGFloat {
set {
layer.borderWidth = newValue
}
get {
return layer.borderWidth
}
}
// Border color
@IBInspectable
public var borderColor: UIColor? {
set {
layer.borderColor = newValue?.cgColor
}
get {
if let borderColor = layer.borderColor {
return UIColor(cgColor: borderColor)
}
return nil
}
}
}
Ardından, arayüz oluşturucu ayar gölgesi AÇIK ve köşe yarıçapında UIView'inizi aşağıdaki gibi seçmeniz yeterlidir :
Sonuç!
İşte masksToBounds çatışma sorununun çözümü, benim için çalışıyor.
CorderRadius / borderColor / shadow ve benzerlerini ayarladıktan sonra masksToBounds öğesini NO olarak ayarlayın:
v.layer.masksToBounds = NO;
Gölge + Sınır + Köşe Yarıçapı
scrollview.backgroundColor = [UIColor whiteColor];
CALayer *ScrlViewLayer = [scrollview layer];
[ScrlViewLayer setMasksToBounds:NO ];
[ScrlViewLayer setShadowColor:[[UIColor lightGrayColor] CGColor]];
[ScrlViewLayer setShadowOpacity:1.0 ];
[ScrlViewLayer setShadowRadius:6.0 ];
[ScrlViewLayer setShadowOffset:CGSizeMake( 0 , 0 )];
[ScrlViewLayer setShouldRasterize:YES];
[ScrlViewLayer setCornerRadius:5.0];
[ScrlViewLayer setBorderColor:[UIColor lightGrayColor].CGColor];
[ScrlViewLayer setBorderWidth:1.0];
[ScrlViewLayer setShadowPath:[UIBezierPath bezierPathWithRect:scrollview.bounds].CGPath];
İşte bir UIView için Swift 3'teki sürümüm
let corners:UIRectCorner = [.bottomLeft, .topRight]
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
mask.fillColor = UIColor.white.cgColor
let shadowLayer = CAShapeLayer()
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowOffset = CGSize(width: 0.0, height: 4.0)
shadowLayer.shadowRadius = 6.0
shadowLayer.shadowOpacity = 0.25
shadowLayer.shadowPath = mask.path
self.layer.insertSublayer(shadowLayer, at: 0)
self.layer.insertSublayer(mask, at: 1)
Swift 4: UIView'in Alt Sınıfını Oluşturun
class ShadowView: UIView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// corner radius
self.layer.cornerRadius = 10
// border
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.black.cgColor
// shadow
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 3, height: 3)
self.layer.shadowOpacity = 0.7
self.layer.shadowRadius = 4.0
}
}
Kullanımı ..
Eğer uçlarınızı değiştirmek ve hiyerarşiyi önerilen David C. olarak görmek istemiyorsanız, bu yöntem sizin için yapacaktır. UIImageView'ınıza yuvarlatılmış köşeler ve gölge eklemek için sadece bu yöntemi kullanın, örneğin:
[Utils roundCornersForImageView:myImageView withCornerRadius:6.0
andShadowOffset:2.0];
(!) Performans nedenleriyle, bu kodu UITableView gibi bir şeyde kullanmanın iyi bir fikir olduğunu düşünmüyorum, çünkü bu kod görünüm hiyerarşisini değiştirir. Bu yüzden ucunuzu değiştirmenizi ve gölge efekti için bir kap görünümü eklemenizi ve Davic C. kodunu kullanmanızı öneririm.
+ (void)roundCornersForImageView:(UIImageView *)imageView
withCornerRadius:(float)cornerRadius andShadowOffset:(float)shadowOffset
{
const float CORNER_RADIUS = cornerRadius;
const float BORDER_WIDTH = 1.0;
const float SHADOW_OFFSET = shadowOffset;
const float SHADOW_OPACITY = 0.8;
const float SHADOW_RADIUS = 3.0;
//Our old image now is just background image view with shadow
UIImageView *backgroundImageView = imageView;
UIView *superView = backgroundImageView.superview;
//Make wider actual visible rect taking into account shadow
//offset
CGRect oldBackgroundFrame = backgroundImageView.frame;
CGRect newBackgroundFrame = CGRectMake(oldBackgroundFrame.origin.x, oldBackgroundFrame.origin.y, oldBackgroundFrame.size.width + SHADOW_OFFSET, oldBackgroundFrame.size.height + SHADOW_OFFSET);
[backgroundImageView removeFromSuperview];
backgroundImageView.frame = newBackgroundFrame;
//Make new UIImageView with rounded corners and put our old image
CGRect frameForRoundedImageView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
UIImageView *roundedImageView = [[UIImageView alloc]initWithFrame:frameForRoundedImageView];
roundedImageView.image = imageView.image;
[roundedImageView.layer setCornerRadius:CORNER_RADIUS];
[roundedImageView.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[roundedImageView.layer setBorderWidth:BORDER_WIDTH];
[roundedImageView.layer setMasksToBounds:YES];
//Set shadow preferences
[backgroundImageView setImage:nil];
[backgroundImageView.layer setShadowColor:[UIColor blackColor].CGColor];
[backgroundImageView.layer setShadowOpacity:SHADOW_OPACITY];
[backgroundImageView.layer setShadowRadius:SHADOW_RADIUS];
[backgroundImageView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];
//Add out two image views back to the view hierarchy.
[backgroundImageView addSubview:roundedImageView];
[superView addSubview:backgroundImageView];
}
Eski iplik hala geçerli ...
Daniel Gindi'nin yöntemini düğmelerle de kullanmayı mümkün kılmak için düzenledim. Herhangi birinin yuvarlak köşelere ihtiyacı varsa veya yuvarlak köşeleri ve bir sınırı birleştirmek istiyorsa, görünümün bu yönteme geçirilen katmanına ayarlanması gerekir. Rasterleştirmeyi biraz hızlandırmak için de ayarladım.
+ (UIView*)putView:(UIView*)view insideShadowWithColor:(CGColorRef)color
andRadius:(CGFloat)shadowRadius
andOffset:(CGSize)shadowOffset
andOpacity:(CGFloat)shadowOpacity
{
// Must have same position like "view"
UIView *shadow = [[UIView alloc] initWithFrame:view.frame];
shadow.layer.contentsScale = [UIScreen mainScreen].scale;
shadow.userInteractionEnabled = YES; // Modify this if needed
shadow.layer.shadowColor = color;
shadow.layer.shadowOffset = shadowOffset;
shadow.layer.shadowRadius = shadowRadius;
shadow.layer.masksToBounds = NO;
shadow.clipsToBounds = NO;
shadow.layer.shadowOpacity = shadowOpacity;
shadow.layer.rasterizationScale = [UIScreen mainScreen].scale;
shadow.layer.shouldRasterize = YES;
[view.superview insertSubview:shadow belowSubview:view];
[shadow addSubview:view];
// Move view to the top left corner inside the shadowview
// ---> Buttons etc are working again :)
view.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
return shadow;
}
Aşağıdakiler benim için en iyi sonucu verdi (bu kod UIView uzantısında yer alıyor, bu yüzden kendi kendine gölge ve yuvarlak köşe eklememiz gereken bazı UIView'i gösteriyor)
- (void)addShadowViewWithCornerRadius:(CGFloat)radius {
UIView *container = self.superview;
if (!container) {
return;
}
UIView *shadowView = [[UIView alloc] init];
shadowView.translatesAutoresizingMaskIntoConstraints = NO;
shadowView.backgroundColor = [UIColor lightGrayColor];
shadowView.layer.cornerRadius = radius;
shadowView.layer.masksToBounds = YES;
[container addSubview:shadowView];
[container bringSubviewToFront:shadowView];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:2.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0.0]];
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:2.0]];
[container sendSubviewToBack:shadowView];
}
Bu ve diğer kod örnekleri arasındaki temel fark, bunun gölge görünümünü bir kardeş görünümü olarak eklemesidir (mevcut görünümü gölge görünümünün alt görünümü olarak eklemeye karşı), böylece mevcut görünüm hiyerarşisini herhangi bir şekilde değiştirme ihtiyacını ortadan kaldırır.
daniel.gindi'nin yukarıdaki cevabı benim için hile yaptı! (+1 daniel) Ancak, küçük ayarlamalar yapmak zorunda kaldım - shadowFrame boyutunu görünümün kare boyutuyla aynı olacak şekilde değiştirmek ve kullanıcı etkileşimini etkinleştirmek zorunda kaldım. Güncellenmiş kod:
+ (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
CGRect shadowFrame; // Modify this if needed
// Modified this line
shadowFrame.size = CGSizeMake(view.frame.size.width, view.frame.size.height);
shadowFrame.origin.x = 0.f;
shadowFrame.origin.y = 0.f;
UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
// Modified this line
shadow.userInteractionEnabled = YES;
shadow.layer.shadowColor = color.CGColor;
shadow.layer.shadowOffset = shadowOffset;
shadow.layer.shadowRadius = shadowRadius;
shadow.layer.masksToBounds = NO;
shadow.clipsToBounds = NO;
shadow.layer.shadowOpacity = shadowOpacity;
[shadow addSubview:view];
return shadow;
}
Benim durumumda, bu bir üçüncü taraf görünüm denetleyicisine eklemek için çalışıyordu eklemek istiyorum, yani kod üzerinde doğrudan kontrol yoktu. Yani, yukarıdaki işlevi nasıl kullandım:
UIView *shadow = [self putView:vc.view
insideShadowWithColor:[UIColor blackColor]
andRadius:5.0
andOffset:CGSizeMake(0.0, 0.0)
andOpacity:1.0];
vc.view = shadow;
vc.view.layer.cornerRadius = 5.0;
vc.view.layer.masksToBounds = YES;
Daniel.gindi kodunda bazı değişiklikler yapıyorum
Çalıştırmak için ihtiyacınız olan her şey bu.
+ (void)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andBlur: (CGFloat)blur andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
{
CGRect shadowFrame = view.frame;
UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
shadow.backgroundColor = [UIColor redColor];
shadow.userInteractionEnabled = YES; // Modify this if needed
shadow.layer.shadowColor = color.CGColor;
shadow.layer.shadowOffset = shadowOffset;
shadow.layer.shadowRadius = blur;
shadow.layer.cornerRadius = view.layer.cornerRadius;
shadow.layer.masksToBounds = NO;
shadow.clipsToBounds = NO;
shadow.layer.shadowOpacity = shadowOpacity;
[view.superview insertSubview:shadow belowSubview:view];
}
Bunu UIViews
başarmak için iki tane kullanmanız gerekir . Biri UIView
gölge gibi, diğeri yuvarlak kenarlık için çalışacaktır.
İşte kod pasajı a'nın Class Method
yardımıyla protocol
:
@implementation UIMethods
+ (UIView *)genComposeButton:(UIViewController <UIComposeButtonDelegate> *)observer;
{
UIView *shadow = [[UIView alloc]init];
shadow.layer.cornerRadius = 5.0;
shadow.layer.shadowColor = [[UIColor blackColor] CGColor];
shadow.layer.shadowOpacity = 1.0;
shadow.layer.shadowRadius = 10.0;
shadow.layer.shadowOffset = CGSizeMake(0.0f, -0.5f);
UIButton *btnCompose = [[UIButton alloc]initWithFrame:CGRectMake(0, 0,60, 60)];
[btnCompose setUserInteractionEnabled:YES];
btnCompose.layer.cornerRadius = 30;
btnCompose.layer.masksToBounds = YES;
[btnCompose setImage:[UIImage imageNamed:@"60x60"] forState:UIControlStateNormal];
[btnCompose addTarget:observer action:@selector(btnCompose_click:) forControlEvents:UIControlEventTouchUpInside];
[shadow addSubview:btnCompose];
return shadow;
}
Yukarıdaki kodda , düğme tıklamasıyla tetiklenecek btnCompose_click:
bir @required
temsilci yöntemi haline gelecektir .
Ve burada UIViewController
böyle bir düğme ekledim :
UIView *btnCompose = [UIMethods genComposeButton:self];
btnCompose.frame = CGRectMake(self.view.frame.size.width - 75,
self.view.frame.size.height - 75,
60, 60);
[self.view addSubview:btnCompose];
Sonuç şöyle görünecektir:
Bu yazıdan çok sayıda çözüm denedim ve aşağıdaki çözümle sonuçlandım. Bu, gölgeyi net bir renk görünümünde düşürmeniz gerekmediği sürece tam kanıtlı bir çözümdür .
- (void)addShadowWithRadius:(CGFloat)shadowRadius withOpacity:(CGFloat)shadowOpacity withOffset:(CGSize)shadowOffset withColor:(UIColor *)shadowColor withCornerradius:(CGFloat)cornerRadius
{
UIView *viewShadow = [[UIView alloc]initWithFrame:self.frame];
viewShadow.backgroundColor = [UIColor whiteColor];
viewShadow.layer.shadowColor = shadowColor.CGColor;
viewShadow.layer.shadowOffset = shadowOffset;
viewShadow.layer.shadowRadius = shadowRadius;
viewShadow.layer.shadowOpacity = shadowOpacity;
viewShadow.layer.cornerRadius = cornerRadius;
viewShadow.layer.masksToBounds = NO;
[self.superview insertSubview:viewShadow belowSubview:self];
[viewShadow setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0]];
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
[self layoutIfNeeded];
self.layer.cornerRadius = cornerRadius;
self.layer.masksToBounds = YES;
}
Aşağıdaki gibi gölge uygulamak için gerekli kenarlara sahip UIView uzantısı oluşturdum
enum AIEdge:Int {
case
Top,
Left,
Bottom,
Right,
Top_Left,
Top_Right,
Bottom_Left,
Bottom_Right,
All,
None
}
extension UIView {
func applyShadowWithCornerRadius(color:UIColor, opacity:Float, radius: CGFloat, edge:AIEdge, shadowSpace:CGFloat) {
var sizeOffset:CGSize = CGSize.zero
switch edge {
case .Top:
sizeOffset = CGSize(width: 0, height: -shadowSpace)
case .Left:
sizeOffset = CGSize(width: -shadowSpace, height: 0)
case .Bottom:
sizeOffset = CGSize(width: 0, height: shadowSpace)
case .Right:
sizeOffset = CGSize(width: shadowSpace, height: 0)
case .Top_Left:
sizeOffset = CGSize(width: -shadowSpace, height: -shadowSpace)
case .Top_Right:
sizeOffset = CGSize(width: shadowSpace, height: -shadowSpace)
case .Bottom_Left:
sizeOffset = CGSize(width: -shadowSpace, height: shadowSpace)
case .Bottom_Right:
sizeOffset = CGSize(width: shadowSpace, height: shadowSpace)
case .All:
sizeOffset = CGSize(width: 0, height: 0)
case .None:
sizeOffset = CGSize.zero
}
self.layer.cornerRadius = self.frame.size.height / 2
self.layer.masksToBounds = true;
self.layer.shadowColor = color.cgColor
self.layer.shadowOpacity = opacity
self.layer.shadowOffset = sizeOffset
self.layer.shadowRadius = radius
self.layer.masksToBounds = false
self.layer.shadowPath = UIBezierPath(roundedRect:self.bounds, cornerRadius:self.layer.cornerRadius).cgPath
}
}
Son olarak, UIView alt sınıflarınızdan herhangi biri için gölge işlevini aşağıdaki gibi çağırabilirsiniz, ayrıca gölge uygulanacak kenarı belirtebilir, aşağıdaki yöntem çağrısının parametrelerini değiştirmenize göre farklı varyasyonlar deneyebilirsiniz.
viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)
Sonuç resmi
Evan Mulawski'nin verdiği cevap mükemmel bir şekilde çalışacaktır. Yakalama, görünüm için arka plan rengini clearColor ve masksToBounds özelliğini NO olarak ayarlamanızdır.
Görünüm için istediğiniz rengi ayarlayabilirsiniz,
v.layer.backgroundColor = your color;
Bu yardımcı olur umarım..
Yuvarlatılmış köşeleri ve yuvarlatılmış gölgeleriyle, yolları rahatsız etmeden böyle yaparsınız.
//Inner view with content
[imageView.layer setBorderColor:[[UIColor lightGrayColor] CGColor]];
[imageView.layer setBorderWidth:1.0f];
[imageView.layer setCornerRadius:8.0f];
[imageView.layer setMasksToBounds:YES];
//Outer view with shadow
UIView* shadowContainer = [[UIView alloc] initWithFrame:imageView.frame];
[shadowContainer.layer setMasksToBounds:NO];
[shadowContainer.layer setShadowColor:[[UIColor blackColor] CGColor]];
[shadowContainer.layer setShadowOpacity:0.6f];
[shadowContainer.layer setShadowRadius:2.0f];
[shadowContainer.layer setShadowOffset: CGSizeMake(0.0f, 2.0f)];
[shadowContainer addSubview:imageView];
İçerikli görünüm, benim durumumda bir UIImageView, bir köşe yarıçapına sahiptir ve bu nedenle sınırlara maskelemek zorundadır.
Gölgeler için eşit boyutta başka bir görünüm oluştururuz, maskToBounds değerini NO olarak ayarlarız ve ardından içerik görünümünü kapsayıcı görünümüne ekleriz (örn. ShadowContainer).
Bu sorunu çözmek için bu UIView kategori yöntemini yazıyorum, gölge ve köşe yarıçapı için ayrı görünümler kullanıyor.
-(UIView *)shadowedWrapViewWithBounds:(CGRect)bounds {
UIView *baseView = [[UIView alloc] init];
baseView.bounds = bounds;
baseView.backgroundColor = [UIColor clearColor];
baseView.layer.shadowColor = [UIColor blackColor].CGColor;
baseView.layer.shadowOffset = CGSizeMake(0, 0);
baseView.layer.shadowOpacity = 0.7;
baseView.layer.shadowRadius = 4.0;
// improve performance
baseView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:baseView.bounds cornerRadius:4].CGPath;
baseView.layer.shouldRasterize = YES;
baseView.layer.rasterizationScale = [UIScreen mainScreen].scale;
[baseView addSubview:self];
//use Masonry autolayout, self can set corner radius
[self makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(baseView);
}];
return baseView;
}
UICollectionViewCell'i yuvarlak hale getirmek ve Gölgeler eklemek için Swift 4 Çözümü herhangi bir uzantı ve komplikasyon olmadan :)
Not: Basit görünümler için, örneğin Düğmeler. Bu yayındaki @ suragch'ın Cevabına bakınız. https://stackoverflow.com/a/34984063/7698092 . Düğmeler için başarıyla test edildi
Durumunda herhangi bir eğer hala mücadele etmek yuvarlamak köşeleri ve eklemek gölgeleri aynı anda. Bu çözüm UICollectionViewCell ile çalışsa da, herhangi bir görünüme genelleştirilebilir.
Bu teknik benim için herhangi bir uzantı ve karmaşık şeyler yapmadan çalıştı. StoryBoard ile çalışıyorum.
teknik
StoryBoard'da UICollectionViewCell'inize bir UIView ("containerView" diyelim) eklemeli ve bu kapsayıcıView içine gerekli tüm görünümleri (düğmeler, resimler vb.) Eklemelisiniz. Ekran görüntüsüne bakın.
ContainerView için çıkışı bağlayın. CellforItemAtIndexPath delege işlevine aşağıdaki kod satırlarını ekleyin.
//adds shadow to the layer of cell
cell.layer.cornerRadius = 3.0
cell.layer.masksToBounds = false
cell.layer.shadowColor = UIColor.black.cgColor
cell.layer.shadowOffset = CGSize(width: 0, height: 0)
cell.layer.shadowOpacity = 0.6
//makes the cell round
let containerView = cell.containerView!
containerView.layer.cornerRadius = 8
containerView.clipsToBounds = true
Çıktı
extension UIView {
func dropRoundedShadowForAllSides() {
let backgroundView = UIView(frame:self.frame)
let radius = frame.height/2
backgroundView.layer.masksToBounds = false
self.layer.masksToBounds = true
backgroundView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
backgroundView.layer.shadowRadius = 4
backgroundView.layer.shadowOpacity = 0.4
let path = UIBezierPath()
// Start at the Top Left Corner + radius distance
path.move(to: CGPoint(x: 2*radius, y: 0.0))
// Move to the Top Right Corner - radius distance
path.addLine(to: CGPoint(x: backgroundView.frame.size.width - radius, y: 0.0))
// Move to top right corner + radius down as curve
let centerPoint1 = CGPoint(x:backgroundView.frame.size.width - radius,y:radius)
path.addArc(withCenter: centerPoint1, radius: radius, startAngle: 3*(.pi/2), endAngle: 0, clockwise: true)
// Move to the Bottom Right Corner - radius
path.addLine(to: CGPoint(x: backgroundView.frame.size.width, y: backgroundView.frame.size.height - radius))
// Move to top right corner + radius left as curve
let centerPoint2 = CGPoint(x:backgroundView.frame.size.width - radius,y:backgroundView.frame.size.height - radius)
path.addArc(withCenter: centerPoint2, radius: radius, startAngle: 0, endAngle: .pi/2, clockwise: true)
// Move to the Bottom Left Corner - radius
path.addLine(to: CGPoint(x: radius, y: backgroundView.frame.size.height))
// Move to left right corner - radius up as curve
let centerPoint3 = CGPoint(x:radius,y:backgroundView.frame.size.height - radius)
path.addArc(withCenter: centerPoint3, radius: radius, startAngle: .pi/2, endAngle: .pi, clockwise: true)
// Move to the top Left Corner - radius
path.addLine(to: CGPoint(x: 0, y: radius))
// Move to top right corner + radius down as curve
let centerPoint4 = CGPoint(x:radius,y:radius)
path.addArc(withCenter: centerPoint4, radius: radius, startAngle: .pi, endAngle: 3 * (.pi/2), clockwise: true)
path.close()
backgroundView.layer.shadowPath = path.cgPath
if let superView = self.superview {
superView.addSubview(backgroundView)
superView.sendSubview(toBack: backgroundView)
superView.bringSubview(toFront: self)
}
}
}