모서리가 둥글고 그림자가 드리워진 UIView?
저는 몇 년 동안 애플리케이션을 연구해 왔고 간단한 디자인 요청을 받았습니다. UI 뷰에서 모서리를 둥글게 만들고 드롭 섀도우를 추가하세요.하기에 따라 하기.
나는 커스텀을 원합니다.UIView
: 저는 둥근 모서리가 있는 빈 흰색 뷰와 밝은 드롭 섀도우(조명 효과 없음)를 원했습니다.나는 그것들을 하나씩 할 수 있지만 보통.clipToBounds
/maskToBounds
충돌이 발생합니다.
스위프트
// 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
옵션 탐색
문제 1: 섀도가 잘립니다.
보기의 범위에 내용을 클리핑하려는 하위 계층 또는 하위 뷰(이미지와 같은)가 있는 경우 어떻게 해야 합니까?
우리는 이것을 성취할 수 있습니다.
blueView.layer.masksToBounds = true
, (또는,는,blueView.clipsToBounds = true
동일한 결과를 제공합니다.)
하지만, 이런!그림자도 범위를 벗어났기 때문에 그림자가 잘렸습니다!무엇을 해야 하나?무엇을 해야 하나?
해결책
그림자와 테두리에 대해 별도의 뷰를 사용합니다.기본 보기는 투명하며 그림자가 있습니다.테두리 보기는 테두리에 있는 다른 하위 내용을 클리핑합니다.
// 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)
그러면 다음과 같은 결과가 나타납니다.
문제 2: 성능 저하
둥근 모서리와 그림자를 추가하면 성능이 크게 향상될 수 있습니다.섀도에 대해 미리 정의된 경로를 사용하고 래스터화하도록 지정하여 성능을 향상시킬 수 있습니다.위의 예에 다음 코드를 추가할 수 있습니다.
baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale
자세한 내용은 이 게시물을 참조하십시오.여기도 보고 여기도 보세요.
이 답변은 Swift 4와 Xcode 9로 테스트되었습니다.
은 테두리, 반지름 및다음코조각리테은두드다및다추가니음합에섀를도드롭에 합니다.v
,aUIView
:
// 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)];
Swift 5 버전:
// border radius
v.layer.cornerRadius = 30.0
// border
v.layer.borderColor = UIColor.lightGray.cgColor
v.layer.borderWidth = 1.5
// drop shadow
v.layer.shadowColor = UIColor.black.cgColor
v.layer.shadowOpacity = 0.8
v.layer.shadowRadius = 3.0
v.layer.shadowOffset = CGSize(width: 2.0, height: 2.0)
필요에 따라 설정을 조정할 수 있습니다.
또한 QuartzCore 프레임워크를 프로젝트에 추가하고 다음을 수행합니다.
#import <QuartzCore/QuartzCore.h>
관련된 다른 답변 보기masksToBounds
.
메모
일부 경우에는 작동하지 않을 수 있습니다.이 방법이 수행 중인 다른 그리기 작업을 방해하는 경우 다음 답변을 참조하십시오.
GitHub에서 예제 프로젝트를 확인하여 구성 요소를 올바르게 사용하는지 확인하십시오.
추가적인 하위 보기 또는 하위 분류가 없는 간단한 Swift 5 솔루션:
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
}
}
호출하기 전에 모서리 반지름 및 기타 속성으로 보기를 설정해야 합니다. addShadow
.
그 후에, 그냥 이것을 전화하세요.viewDidLoad
다음과 같이:
button.addShadow(offset: CGSize.init(width: 0, height: 3), color: UIColor.black, radius: 2.0, opacity: 0.35)
최종 결과:
매우 쉽고 간단합니다!
한 가지 방법은 모서리가 둥근 뷰를 드롭 그림자가 있는 뷰에 배치하는 것입니다.
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];
그런 다음 원하는 곳에 섀도 뷰를 추가할 수 있습니다.
이것은 저에게 효과가 있었습니다.비결은 배경색을 주 뷰에서 레이어로 이동하는 것이었습니다.
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 ;
컨테이너 뷰에 섀도 경로를 할당할 때 다음과 같은 트릭을 사용하여 문제를 해결했습니다.
[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]
그림자에 지정된 경로는 셀에 포함된 배경과 동일한 모서리 반지름을 가진 둥근 직사각형입니다.
//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]];
은.corners
대 대subviews
대 대masksToBounds
그런 다음 내 기능을 사용해 보십시오.
- (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;
}
당신이 보기에 그렇게 생각합니다.보기가 둥근 모서리를 가지든, 크기와 모양에 관계없이 멋진 그림자가 그려집니다.
때할 수 예: 테이블을예수때함있참반수다유값니환의합지만록도할사조용제거할예▁just▁so▁of▁function▁((다▁the).insertSubview:aboveView:
)
Swift 4와 Xcode 9를 사용하여 다음과 같이 반올림합니다.ImageView
그림자가 드리워져 있고, 테두리가 있습니다.
//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)
영상을 원형으로 표시하려면: (그리고 테두리 없이 표시됨)
let cornerRadius = imageWidth / 2
사해야합다를 .shadowView
그리고.roundView
섀도 뷰
- 배경색이 있어야 합니다.
- 뒤에 .
roundView
- 을 만드는 것입니다.
shadowView
약간의 내부, 그리고 그것의 그림자는 빛을 발해야 합니다.을 합니다.insets
그 록도하록shadowView
뒤로는 전혀 보이지 않습니다.roundView
원경
- 하위 뷰를 클립해야 합니다.
코드
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
}
또는 아래와 같이 지정하지 않고 수행할 수 있습니다.clipToBounds/maskToBounds
layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.8
여기 확실히 작동할 수 있는 해결책이 있습니다!
아래와 같이 섀도를 적용하기 위해 필요한 가장자리가 있는 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)
}
누군가 이것이 유용하다고 생각하기를 바랍니다!
다음은 결과 영상입니다.
UIView에서 도우미를 만들었습니다.
@interface UIView (Helper)
- (void)roundCornerswithRadius:(float)cornerRadius
andShadowOffset:(float)shadowOffset;
@end
당신은 이렇게 부를 수 있습니다.
[self.view roundCornerswithRadius:5 andShadowOffset:5];
구현 내용은 다음과 같습니다.
- (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];
}
swift 4에서 빠르게 테스트된 것.
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
}
}
}
프로듀스
이렇게 Inspector에서 활성화하면 다음과 같습니다.
User Defined Runtime 특성이 추가되어 다음과 같은 결과가 발생합니다.
(에 (이전에추내용은한가▁previous내)를 추가했습니다cornerRadius = 8
)
:)
그림자가 있는 둥근 코너 뷰를 하루 종일 조사한 후, 저는 여기에 제 커스텀 뷰 클래스를 게시하게 되어 기쁩니다. 이 질문을 마치기를 바랍니다.
둥근 모서리 그림자 뷰.h
#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
따라서 뷰에서 하위 뷰를 추가하거나 대상 뷰에서 하위 뷰를 추가할 필요가 없습니다. 현재 뷰에서 레이어를 하나 추가하기만 하면 3단계를 수행하여 완료할 수 있습니다!
코드의 주석을 자세히 살펴보십시오. 구성 요소를 이해하는 데 도움이 됩니다!
Swift 3 & IB 검사 불가능한 솔루션:
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를 선택합니다.
결과!
iOS 그림자 및 모서리 반지름
은 다을사용섀설수있습다니정할도를을 사용하여 그림자를 할 수 .layer
//shadow
view1.layer.shadowColor = UIColor.magenta.cgColor
view1.layer.shadowOffset = CGSize(width: 0, height: 0)
view1.layer.shadowOpacity = 1
view1.layer.shadowRadius = 5
//cornerRadius
view1.layer.cornerRadius = 5
시각화
1.그림자 오프셋.너비, 2.그림자 간격띄우기.높이, 3.그림자 불투명도, 4.그림자 반지름
![](https://i.stack.imgur.com/zqlMk.gif)
![](https://i.stack.imgur.com/q7o2M.gif)
![](https://i.stack.imgur.com/r5bDx.gif)
![](https://i.stack.imgur.com/JRybG.gif)
- 그림자 간격띄우기 너비 및 높이는 임의입니다.
shadowOpacity
~ ~ 1µm입니다.shadowRadius
는 00에서입니다.
간단한 작업이 아닙니다.
섀도는 다음을 기준으로만 계산되지 않습니다.boundaries
그리고.cornerRaduis
그림자를 만드는 동안 다음 항목이 고려됩니다.
- 하위 뷰 도면층
- 서브레이어
content
(Backing Image
)
view1.backgroundColor = .clear
view1.layer.contents = UIImage(named: "ring")?.cgImage
view1.layer.contentsScale = UIScreen.main.scale
![](https://i.stack.imgur.com/IcMGq.png)
축척 계수(contentsScale
,rasterizationScale
- 은 1) - 기값은 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)
사용하다UIScreen.main.scale
성능
용사를 합니다.layer.cornerRadius
,shadow
정도 영향을 .
에 대해서는layer.cornerRadius
성능:
하기 용하기적.color blending
사용됨 [자세히 읽어보기]
에 대해서는shadow
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
로 용사가를 합니다.shadowPath
내부 정적 계층에 사용됩니다.기본적으로 다음과 같습니다.nil
그렇기 때문에 UIKit은 화면 밖에서 보기를 생성하고 이 정보를 기반으로 그림자를 생성해야 합니다.따라서 경로를 미리 정의하고 설정할 수 있습니다.또 다른 장점은 원하는 대로 사용자 정의 섀도를 만들 수 있다는 것입니다.
view1.layer.shadowPath = UIBezierPath(roundedRect: view1.bounds, cornerRadius: 50).cgPath
단점 - 동적이지 않습니다.뷰가 경계(폭, 높이, 모서리 반지름...)를 변경하는 경우 그림자는 이전 경계(이전 경계) 그대로 유지됩니다.보기의 위치가 변경된 경우(이동, 스크롤됨)shadowPath
입니다.
캐시 래스터라이즈
여기 maskToBounds 충돌 문제에 대한 해결책이 있습니다. 저에게 효과가 있습니다.
코더 Radius/borderColor/shadow 등을 설정한 후 maskToBounds를 NO로 설정합니다.
v.layer.masksToBounds = NO;
+ 반지름 + 모서리 반지름 + 모서리 반지름
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];
이것은 UIView용 Swift 3 버전입니다.
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의 하위 클래스 만들기
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
}
}
사용 중...
만약 당신이 David C의 제안대로 당신의 닙과 보기 계층을 바꾸고 싶지 않다면, 이 방법이 당신을 위해 그것을 할 것입니다.UIImageView에 둥근 모서리와 그림자를 추가하려면 다음과 같은 방법을 사용합니다.
[Utils roundCornersForImageView:myImageView withCornerRadius:6.0
andShadowOffset:2.0];
(!) 성능상의 이유로 UITableView와 같은 곳에서 이 코드를 사용하는 것은 좋은 생각이 아니라고 생각합니다. 이 코드는 보기 계층을 변경하기 때문입니다.그래서 저는 당신의 닙을 변경하고 섀도우 효과를 위한 컨테이너 뷰를 추가하고 데이비드 C. 코드를 사용하는 것을 제안하겠습니다.
+ (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];
}
이전 스레드가 여전히 현재 상태입니다...
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 확장자에 있으므로 self는 그림자와 둥근 모서리를 추가해야 하는 일부 UIView를 나타냅니다).
- (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];
}
이것과 다른 코드 샘플의 주요 차이점은 현재 뷰를 섀도 뷰의 하위 뷰로 추가하는 것과 달리 섀도 뷰를 형제 뷰로 추가하므로 기존 뷰 계층 구조를 수정할 필요가 없습니다.
확장과 합병증 없이 UICollectionViewCell을 원형으로 만들고 그림자를 추가하는 Swift 4 솔루션 :)
참고: 버튼과 같은 간단한 보기용입니다.이 게시물의 @suragch's Answer를 참조하십시오.https://stackoverflow.com/a/34984063/7698092 .버튼 테스트 성공
여전히 코너를 돌면서 동시에 그림자를 더하기 위해 고군분투하는 사람이 있다면 말입니다.이 솔루션은 UICollectionViewCell과 함께 작동하지만 모든 보기로 일반화할 수 있습니다.
이 기술은 저에게 아무런 확장이나 복잡한 것 없이 효과가 있었습니다.저는 storyBoard와 함께 일하고 있습니다.
기술.
스토리보드의 UICollectionViewCell 내에 UIView("containerView"라고 가정)를 추가하고 이 컨테이너View 내에 필요한 모든 뷰(버튼, 이미지 등)를 추가해야 합니다.스크린샷을 참조하십시오.
containerView용 콘센트를 연결합니다.Cell for ItemAtIndexPath 대리 함수에 다음 코드 행을 추가합니다.
//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
산출량
시뮬레이터 스크린샷 참조
daniel.gindi의 위의 대답은 나에게 효과가 있었습니다! (+1 daniel)하지만 저는 섀도우 프레임 크기를 뷰의 프레임 크기와 동일하게 변경하고 사용자 상호 작용을 활성화하는 등 사소한 조정을 해야 했습니다.다음은 업데이트된 코드입니다.
+ (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;
daniel.gindi의 코드를 약간 변경했습니다.
이것이 당신이 그것을 작동시키기 위해 필요한 전부입니다.
+ (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];
}
두 개를 사용해야 합니다.UIViews
이를 위해하나.UIView
그림자처럼 작동하고 다른 하나는 둥근 테두리에 작동합니다.
여기 코드 스니펫이 있습니다.Class Method
의 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;
}
의 btnCompose_click:
▁a▁become다▁will니가 될 것입니다.@required
버튼 클릭 시 실행되는 delegate 메서드입니다.
에 제 그고여기버추튼가다니습했을에리▁▁my▁button다▁a니▁and습▁added▁i추▁here가했그에 버튼을 추가했습니다.UIViewController
다음과 같이:
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];
결과는 다음과 같습니다.
저는 이 게시물에서 많은 해결책을 시도했고 결국 아래와 같은 해결책을 얻었습니다.선명한 색상 보기에 그림자를 놓을 필요가 없는 경우 이는 완전한 증명 솔루션입니다.
- (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;
}
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)
}
}
Evan Mulawski가 제공한 답변은 완벽하게 작동할 것입니다.이 경우 뷰의 배경색을 clearColor로 설정하고 masksToBounds 속성을 NO로 설정해야 합니다.
보기에 원하는 색상을 설정할 수 있습니다.
v.layer.backgroundColor = your color;
이게 도움이 되길..
길을 가리지 않고 모서리가 둥글고 그림자가 둥근 것이 바로 이런 식으로 말이죠.
//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로 설정한 다음 내용 보기를 컨테이너 보기(예: 그림자 컨테이너)에 추가합니다.
언급URL : https://stackoverflow.com/questions/4754392/uiview-with-rounded-corners-and-drop-shadow
'programing' 카테고리의 다른 글
javascript 실행 시 mongodb 콘솔에 쓸 수 있습니까? (0) | 2023.05.14 |
---|---|
Python에서 try/except를 사용하여 문자열을 Int로 변환 (0) | 2023.05.14 |
Postgre에서 특정 행 내보내기SQL 테이블을 INSERT SQL 스크립트로 사용 (0) | 2023.05.14 |
os.path.join에 대한 Pathlib 대안이 있습니까? (0) | 2023.05.14 |
wpf에서 사용자 지정 윈도우 크롬을 만드는 방법은 무엇입니까? (0) | 2023.05.14 |