문제

나는 바닥 아래에 그림자를 그려 보려고 노력하고있다 UIView 코코아 터치에서. 나는 내가 사용해야한다는 것을 이해한다 CGContextSetShadow() 그림자를 그리려면 Quartz 2D 프로그래밍 안내서는 약간 모호합니다.

  1. 그래픽 상태를 저장하십시오.
  2. 기능을 호출하십시오 CGContextSetShadow, 적절한 값을 전달합니다.
  3. 그림자를 적용하려는 모든 그림을 수행하십시오.
  4. 그래픽 상태를 복원하십시오

나는 다음을 시도했다 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;

동일한 해결책이지만 생각 나게하기 위해 : 스토리 보드에서 직접 그림자를 정의 할 수 있습니다.

전:

enter image description here

당신은 이것을 시도 할 수 있습니다 .... 당신은 가치를 가지고 놀 수 있습니다. 그만큼 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

스프레드가있는 예

Example with spread

기본 그림자를 만듭니다

    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의 기본 그림자 예제

OUTPUT

인터페이스 빌더를 사용한 간단하고 깨끗한 솔루션

프로젝트에서 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
        }
    }
}

그런 다음 유틸리티 패널> 속성 검사관의 모든보기에 대한 인터페이스 빌더에서 사용할 수 있습니다.

Utilities Panel

이제 그림자를 쉽게 설정할 수 있습니다.

메모:
- 그림자는 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
    }
}
}

2 단계. 이제 스토리 보드 에서이 속성을 사용할 수 있습니다.storyboard image

여기에 모든 답을 시도한 후 (나 자신으로!) 이것을 일하는 데 실패한 사람들에게 클립 하위 뷰 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 적절한 방법을 직접 호출합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top