Uiview 아래에서 그림자를 어떻게 그리나요?
-
03-07-2019 - |
문제
나는 바닥 아래에 그림자를 그려 보려고 노력하고있다 UIView
코코아 터치에서. 나는 내가 사용해야한다는 것을 이해한다 CGContextSetShadow()
그림자를 그리려면 Quartz 2D 프로그래밍 안내서는 약간 모호합니다.
- 그래픽 상태를 저장하십시오.
- 기능을 호출하십시오
CGContextSetShadow
, 적절한 값을 전달합니다. - 그림자를 적용하려는 모든 그림을 수행하십시오.
- 그래픽 상태를 복원하십시오
나는 다음을 시도했다 UIView
아강:
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
CGContextRestoreGState(currentContext);
[super drawRect: rect];
}
.. 그러나 이것은 나에게 효과가없고 나는 (a) 다음에 가야 할 곳과 (b) 내가해야 할 일이 있다면 내 UIView
이 일을하려면?
해결책
현재 코드에서는 GState
현재 컨텍스트에서 그림자를 그리도록 구성하십시오. 마지막으로, 당신은 슈퍼 클래스의 구현을 호출합니다. drawRect
: .
그림자 설정의 영향을 받아야하는 모든 도면이 발생해야합니다. ~ 후에
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
하지만 ~ 전에
CGContextRestoreGState(currentContext);
따라서 슈퍼 클래스를 원한다면 drawRect:
그림자에 '포장'되려면 이와 같이 코드를 재 배열하면 어떻습니까?
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
[super drawRect: rect];
CGContextRestoreGState(currentContext);
}
다른 팁
훨씬 쉬운 접근 방식은 초기화에 대한 뷰의 일부 레이어 속성을 설정하는 것입니다.
self.layer.masksToBounds = NO;
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
쿼츠 코어를 가져와야합니다.
#import <QuartzCore/QuartzCore.h>
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 8; // if you like rounded corners
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
응용 프로그램이 느려집니다. 다음 줄을 추가하면보기가 눈에 띄게 직사각형 인 한 성능이 향상 될 수 있습니다.
self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
동일한 해결책이지만 생각 나게하기 위해 : 스토리 보드에서 직접 그림자를 정의 할 수 있습니다.
전:
당신은 이것을 시도 할 수 있습니다 .... 당신은 가치를 가지고 놀 수 있습니다. 그만큼 shadowRadius
흐림 금액을 지시합니다. shadowOffset
그림자가 어디로 가는지 지시합니다.
스위프트 2.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.CGPath
스위프트 3.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.black.cgColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.cgPath
스프레드가있는 예
기본 그림자를 만듭니다
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSizeMake(0.5, 4.0); //Here your control your spread
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
Swift 2.0의 기본 그림자 예제
인터페이스 빌더를 사용한 간단하고 깨끗한 솔루션
프로젝트에서 uiview.swift라는 파일을 추가 (또는 파일에 붙여 넣기 만하면).
import UIKit
@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
}
}
}
그런 다음 유틸리티 패널> 속성 검사관의 모든보기에 대한 인터페이스 빌더에서 사용할 수 있습니다.
이제 그림자를 쉽게 설정할 수 있습니다.
메모:
- 그림자는 IB에서는 런타임에만 나타나지 않습니다.
- Mazen Kasser가 말했듯이
이 작업을 수행하지 못한 사람들에게 [...] 클립 하위 뷰를 확인하십시오 (
clipsToBounds
)가 활성화되지 않았습니다
나는 이것을 나의 utils의 일부로 사용합니다. 이것으로 우리는 그림자를 설정할 수있을뿐만 아니라 어떤 둥근 코너를 얻을 수 있습니다. UIView
. 또한 원하는 색상 그림자를 설정할 수 있습니다. 일반적으로 검은 색이 선호되지만 때로는 배경이 백인이 아닌 경우 다른 것을 원할 수 있습니다. 내가 사용하는 것은 다음과 같습니다.
in utils.m
+ (void)roundedLayer:(CALayer *)viewLayer
radius:(float)r
shadow:(BOOL)s
{
[viewLayer setMasksToBounds:YES];
[viewLayer setCornerRadius:r];
[viewLayer setBorderColor:[RGB(180, 180, 180) CGColor]];
[viewLayer setBorderWidth:1.0f];
if(s)
{
[viewLayer setShadowColor:[RGB(0, 0, 0) CGColor]];
[viewLayer setShadowOffset:CGSizeMake(0, 0)];
[viewLayer setShadowOpacity:1];
[viewLayer setShadowRadius:2.0];
}
return;
}
이것을 사용하려면 이것을 호출해야합니다. [utils roundedLayer:yourview.layer radius:5.0f shadow:YES];
스위프트 3
extension UIView {
func installShadow() {
layer.cornerRadius = 2
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 1)
layer.shadowOpacity = 0.45
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shadowRadius = 1.0
}
}
스토리 보드를 사용하고 싶고 런타임 속성에서 계속 입력하지 않으려면보기에 대한 확장자를 쉽게 만들고 스토리 보드에서 사용할 수있게 할 수 있습니다.
단계 1. 확장자를 만듭니다
extension UIView {
@IBInspectable var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue
}
}
@IBInspectable var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
@IBInspectable var shadowOffset: CGSize {
get {
return layer.shadowOffset
}
set {
layer.shadowOffset = newValue
}
}
@IBInspectable var maskToBound: Bool {
get {
return layer.masksToBounds
}
set {
layer.masksToBounds = newValue
}
}
}
여기에 모든 답을 시도한 후 (나 자신으로!) 이것을 일하는 데 실패한 사람들에게 클립 하위 뷰 Attributes Inspector에서 활성화되지 않습니다 ...
스위프트 3
self.paddingView.layer.masksToBounds = false
self.paddingView.layer.shadowOffset = CGSize(width: -15, height: 10)
self.paddingView.layer.shadowRadius = 5
self.paddingView.layer.shadowOpacity = 0.5
아래와 같이 섀도우 및 코너 반경에 생성 된 내 유틸리티 기능을 사용할 수 있습니다.
- (void)addShadowWithRadius:(CGFloat)shadowRadius withShadowOpacity:(CGFloat)shadowOpacity withShadowOffset:(CGSize)shadowOffset withShadowColor:(UIColor *)shadowColor withCornerRadius:(CGFloat)cornerRadius withBorderColor:(UIColor *)borderColor withBorderWidth:(CGFloat)borderWidth forView:(UIView *)view{
// drop shadow
[view.layer setShadowRadius:shadowRadius];
[view.layer setShadowOpacity:shadowOpacity];
[view.layer setShadowOffset:shadowOffset];
[view.layer setShadowColor:shadowColor.CGColor];
// border radius
[view.layer setCornerRadius:cornerRadius];
// border
[view.layer setBorderColor:borderColor.CGColor];
[view.layer setBorderWidth:borderWidth];
}
그것이 당신을 도울 수 있기를 바랍니다 !!!
모두 잘 대답하지만 한 가지 더 추가하고 싶습니다.
테이블 셀이있을 때 문제가 발생하면 새 셀을 deque로 만들면 그림자에 불일치가 있으므로이 경우 그림자 코드를 레이아웃 서브 뷰 메소드에 배치하여 모든 조건에서 잘 작동하도록해야합니다.
-(void)layoutSubviews{
[super layoutSubviews];
[self.contentView setNeedsLayout];
[self.contentView layoutIfNeeded];
[VPShadow applyShadowView:self];
}
또는 특정보기에 대한 ViewControllers에서 그림자 코드는 다음 방법에 잘 작동하여 잘 작동합니다.
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[self.viewShadow layoutIfNeeded];
[VPShadow applyShadowView:self.viewShadow];
}
보다 일반화 된 양식을 위해 새 개발자에 대한 그림자 구현을 수정했습니다.
/*!
@brief Add shadow to a view.
@param layer CALayer of the view.
*/
+(void)applyShadowOnView:(CALayer *)layer OffsetX:(CGFloat)x OffsetY:(CGFloat)y blur:(CGFloat)radius opacity:(CGFloat)alpha RoundingCorners:(CGFloat)cornerRadius{
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:cornerRadius];
layer.masksToBounds = NO;
layer.shadowColor = [UIColor blackColor].CGColor;
layer.shadowOffset = CGSizeMake(x,y);// shadow x and y
layer.shadowOpacity = alpha;
layer.shadowRadius = radius;// blur effect
layer.shadowPath = shadowPath.CGPath;
}
동료 Xamarians의 경우 Xamarin.ios/C# 버전의 답변은 다음과 같습니다.
public override void DrawRect(CGRect area, UIViewPrintFormatter formatter)
{
CGContext currentContext = UIGraphics.GetCurrentContext();
currentContext.SaveState();
currentContext.SetShadow(new CGSize(-15, 20), 5);
base.DrawRect(area, formatter);
currentContext.RestoreState();
}
주요 차이점은 인스턴스를 획득한다는 것입니다. CGContext
적절한 방법을 직접 호출합니다.