我在一个应用程序上工作了几年,收到了一个简单的设计请求:在UIView上圆角并添加投影。做以下所给的事
我想要一个自定义的UIView…:我只是想要一个空白的白色视图与圆角和光滴阴影(没有照明效果)。我可以逐个执行这些操作,但通常会发生clipToBounds/maskToBounds冲突。
我在一个应用程序上工作了几年,收到了一个简单的设计请求:在UIView上圆角并添加投影。做以下所给的事
我想要一个自定义的UIView…:我只是想要一个空白的白色视图与圆角和光滴阴影(没有照明效果)。我可以逐个执行这些操作,但通常会发生clipToBounds/maskToBounds冲突。
当前回答
你需要添加masksToBounds = true的组合之间的corderRadius shadowRadius。
button.layer.masksToBounds = false;
其他回答
丹尼尔。Gindi上面的回答对我很有用!然而,我不得不做一些小的调整-改变shadowFrame的大小与视图的帧大小相同,并启用用户交互。以下是更新后的代码:
+ (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;
}
我想补充的是,在我的情况下,我试图将此添加到第三方视图控制器,即我没有对代码的直接控制。下面是我如何使用上面的函数:
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;
我写了这个UIView分类方法来解决这个问题,使用单独的视图来表示阴影和角的半径。
-(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;
}
import UIKit
extension UIView {
func addShadow(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
let shadowLayer = CAShapeLayer()
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath //2
shadowLayer.fillColor = fillColor.cgColor //3
shadowLayer.shadowColor = shadowColor.cgColor //4
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = offSet //5
shadowLayer.shadowOpacity = opacity
shadowLayer.shadowRadius = shadowRadius
self.layer.addSublayer(shadowLayer)
}
}
Swift 3 & IBInspectable解决方案: 灵感来自Ade的解决方案
首先,创建一个UIView扩展:
//
// 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
}
}
}
然后,在界面构建器中选择你的UIView,设置阴影ON和角半径,如下所示:
结果!
这就是你怎么做的,有圆角和圆角阴影,而不用担心路径。
//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];
带有内容的视图,在我的例子中是UIImageView,有一个角半径,因此必须屏蔽到边界。
我们为阴影创建另一个同样大小的视图,设置它的maskToBounds为NO,然后将内容视图添加到容器视图(例如shadowContainer)。