我在一个应用程序上工作了几年,收到了一个简单的设计请求:在UIView上圆角并添加投影。做以下所给的事
我想要一个自定义的UIView…:我只是想要一个空白的白色视图与圆角和光滴阴影(没有照明效果)。我可以逐个执行这些操作,但通常会发生clipToBounds/maskToBounds冲突。
我在一个应用程序上工作了几年,收到了一个简单的设计请求:在UIView上圆角并添加投影。做以下所给的事
我想要一个自定义的UIView…:我只是想要一个空白的白色视图与圆角和光滴阴影(没有照明效果)。我可以逐个执行这些操作,但通常会发生clipToBounds/maskToBounds冲突。
当前回答
这对我很管用。窍门是将背景颜色从主视图移到图层中。
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 ;
其他回答
iOS阴影和拐角半径
[iOS CALayer]
[iOS masksToBounds]
[iOS调试渲染]
你可以使用图层设置阴影
view1.layer.shadowColor = UIColor.magenta.cgColor
view1.layer.shadowOffset = CGSize(width: 0, height: 0)
view1.layer.shadowOpacity = 1
view1.layer.shadowRadius = 0
可视化
1. shadowoffset。宽度,2. shadowoffset。高度,3。shadowOpacity 4。shadowRadius
shadowOffset宽度和高度是任意的 shadowOpacity从0到1 shadowRadius从0开始为正
不是简单的任务
请注意,阴影不是仅根据边界和边角raduis计算的。在创建阴影的过程中,需要考虑以下事项:
子视图层 子层 内容(支持图像)
view1.backgroundColor = .clear
view1.layer.contents = UIImage(named: "ring")?.cgImage
view1.layer.contentsScale = UIScreen.main.scale
ScaleFactor(contentsScale, rasterizationScale) -默认为1.0
currentBitmapSize = layerSize * scaleFactor
//non retina
1 point == 1x pixels
//Retina
1 point == 2x pixels
//or
1 point == 3x pixels
//For example to draw line
point(width: 4, height: 2) == 1x pixels(width: 4, height: 2)(8 pixels) == 2x pixels(width: 8, height: 4)(32 pixels)
使用uisscreen .main.scale =当前屏幕的缩放因子
[iOS像素、点数、单位]
的绩效
使用层。角半径,阴影有一些性能影响
至于层。cornerRadius性能:
应用它的颜色混合使用[阅读更多]
至于影子Xcode提示你:
The layer is using dynamic shadows which are expensive to render. If possible try setting shadowPath, or pre-rendering the shadow into an image and putting it under the layer
1. 另外使用shadowPath
用于内部静态层。默认情况下,它是nil,这就是为什么UIKit应该创建一个屏幕外视图,并基于这个信息创建一个阴影。这就是为什么您能够预定义路径并进行设置。另一个优点是,您可以根据需要创建自定义阴影
view1.layer.shadowPath = UIBezierPath(roundedRect: view1.bounds, cornerRadius: 50).cgPath
缺点-缺乏活力。如果视图改变边界(宽度,高度,角半径…),阴影仍然是它是(旧的边界)。如果视图的位置被改变(移动,滚动),shadowPath将是正确的
2. 缓存栅格化
(iOS shouldRasterize)
旧线程仍然当前…
我编辑了Daniel Gindi的方法,使它可以用于按钮等。 如果有人需要圆角,或者想要将圆角和边框结合起来,它必须在视图层上设置,这个视图层被传递给这个方法。我还设置了栅格化来加快一点。
+ (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;
}
在研究了一整天的圆角视图与阴影之后,我很高兴在这里发布我的自定义uiview类,希望结束这个问题:
RoundCornerShadowView.h
#import <UIKit/UIKit.h>
@interface RoundCornerShadowView : UIView
@end
RoundCornerShadowView.m
#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
所以,不需要在视图中添加子视图或在目标视图中添加子视图,只需在当前视图中添加一层,并执行3步即可完成!
仔细查看代码中的注释,这有助于理解组件!
Swift 4解决方案,使UICollectionViewCell圆形和添加阴影,没有任何扩展和并发症:)
注意:对于简单的视图,例如按钮。请看这篇文章中的@suragch的回答。 https://stackoverflow.com/a/34984063/7698092。按钮测试成功
以防有人还在努力使角落圆润,同时添加阴影。虽然这个解决方案适用于UICollectionViewCell,但它可以推广到任何视图。
这个技巧对我来说很有效,不需要做任何扩展和所有复杂的事情。我正在使用storyBoard。
技术
你必须在storyBoard的UICollectionViewCell中添加一个UIView(让我们说它是“containerView”),并在这个containerView中添加所有必需的视图(按钮,图像等)。 见截图。
连接containerView的出口。在CellforItemAtIndexPath委托函数中添加以下代码行。
//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
输出
查看模拟器截图
这里有一个肯定有效的解决方案!
我已经创建了UIView扩展所需的边应用阴影如下
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, cornerRadius: 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 = cornerRadius
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
}
}
最后,你可以为你的UIView子类调用下面的阴影函数,你也可以指定边缘上应用阴影,尝试不同的变化根据你需要改变下面方法调用的参数。
viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)
注意:如果仍然不工作,试着从主线程调用它
DispatchQueue.main.async {
viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)
}
希望有人觉得这有用!
以下是结果图片: