UIView với các góc tròn và bóng đổ?


390

Tôi muốn có một tùy chỉnh UIView...: Tôi chỉ muốn một chế độ xem trắng trống với các góc tròn và bóng đổ ánh sáng (không có hiệu ứng ánh sáng). Tôi có thể làm từng cái một nhưng những xung đột clipToBounds/ thông thường maskToBoundsxảy ra.


1
Vì bạn nói trong một bình luận bên dưới rằng bạn đã làm việc này bằng CoreGraphics, bạn có phiền khi chia sẻ câu trả lời với cộng đồng để bạn có thể giúp đỡ những người khác trong tình huống tương tự, khi họ cố gắng giúp bạn không?
lnafziger

Tôi xin lỗi, điều này đã khá lâu rồi và tôi không còn nguồn nữa. Những gì tôi đã làm là ghi đè -drawRect: và sử dụng UIBezierPath để vẽ hình chữ nhật và áp dụng bóng cho lớp sao lưu chế độ xem ... nếu tôi nhớ chính xác. :)
Aditya Vaidyam

5
Câu trả lời được chấp nhận không hoạt động!
onmyway133

1
Bản sao có thể có của Giving UIView được làm tròn góc

1
@Sachavijay Bạn nên xác minh ngày của cả hai bài viết trước khi bình luận.
Aditya Vaidyam

Câu trả lời:


444

Đoạn mã sau đây thêm đường viền, bán kính đường viền và bóng đổ xuống v, a UIView:

// 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)];

Bạn có thể điều chỉnh các cài đặt cho phù hợp với nhu cầu của bạn.

Ngoài ra, thêm khung QuartzCore vào dự án của bạn và:

#import <QuartzCore/QuartzCore.h>

Xem câu trả lời khác của tôi liên quan masksToBounds.


Ghi chú

Điều này có thể không hoạt động trong mọi trường hợp. Nếu bạn thấy rằng phương pháp này can thiệp vào các hoạt động vẽ khác mà bạn đang thực hiện, vui lòng xem câu trả lời này .


83
Vấn đề với nó là khi tôi đặt bán kính góc, nó đặt maskToBound: CÓ, trong khi bóng yêu cầu clipToBound: NO (trong đó clipToBound thực hiện giống như maskToBound)
Aditya Vaidyam

15
cùng một vấn đề ở đây. Nếu tôi có một màu nền, tôi muốn nó được cắt vào các góc tròn. Để làm điều đó, tôi phải sử dụng maskToBound = TRUE, nhưng sau đó bóng tối biến mất ..
hfossli

3
Đối với những người mới như tôi: Tôi đã phải nhập khung QuartzCore vào dự án của mình để gọi các phương thức trên đối tượng lớp.
SilithCrowe

38
Cách để làm cho điều này hoạt động đúng cách là sử dụng chế độ xem bên trong, nơi chứa đường viền và màu nền của bạn, cả hai đều có bán kính góc. Quan điểm này sẽ được cắt thành giới hạn! Khung nhìn container thứ hai, bên ngoài sẽ chứa khung đầu tiên, có cùng khung, chỉ với một bóng đổ. Tôi đã thực hiện điều này khá nhiều lần để kết hợp đường viền, bóng đổ và bán kính góc. Nó thực sự gây phiền nhiễu, nhưng nó hoạt động thực sự tốt.
Kpmurphy91

23
Không hoạt động. Không biết tại sao có rất nhiều phiếu bầu. Điều này có được áp dụng trong các phiên bản cũ hơn không?
Yarneo

628

Nhanh

nhập mô tả hình ảnh ở đây

// 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

Khám phá các tùy chọn

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Vấn đề 1: Shadow bị cắt bớt

Điều gì xảy ra nếu có các lớp con hoặc các bài phỏng vấn (như một hình ảnh) có nội dung mà chúng tôi muốn đưa vào giới hạn của chế độ xem của chúng tôi?

nhập mô tả hình ảnh ở đây

Chúng ta có thể thực hiện điều này với

blueView.layer.masksToBounds = true

(Ngoài ra, blueView.clipsToBounds = truecho kết quả tương tự .)

nhập mô tả hình ảnh ở đây

Nhưng, ôi không! Cái bóng cũng bị cắt bớt vì nó nằm ngoài giới hạn! Phải làm sao Phải làm sao

Giải pháp

Sử dụng chế độ xem riêng cho bóng và đường viền. Chế độ xem cơ sở là trong suốt và có bóng. Các khung nhìn biên giới clip bất kỳ nhà thầu phụ khác mà nó có biên giới của nó.

// 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)

Điều này cho kết quả như sau:

nhập mô tả hình ảnh ở đây

Vấn đề 2: Hiệu suất kém

Thêm các góc tròn và bóng có thể là một điểm nhấn hiệu suất. Bạn có thể cải thiện hiệu suất bằng cách sử dụng đường dẫn được xác định trước cho bóng và cũng chỉ định rằng nó được rasterized. Các mã sau đây có thể được thêm vào ví dụ trên.

baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale

Xem bài đăng này để biết thêm chi tiết. Xem ở đâyở đây cũng có.

Câu trả lời này đã được thử nghiệm với Swift 4 và Xcode 9.


1
@ EICaptainv2.0, Nếu bạn chỉ muốn một đường viền (và / hoặc bán kính góc) thì bạn không cần một chế độ xem riêng. Chế độ xem riêng dành cho trường hợp bạn cần góc tròn và bóng .
Suragch

2
Điều này không làm việc cho tôi. Khi tôi đặt màu nền trở lại để xóa trên cơ sở Xem một bóng không xuất hiện nữa. Tôi đang làm gì sai?
Rutger Huijsmans

3
Không hoạt động, cài đặt baseView.backgroundColor = UIColor.clearloại bỏ bóng. Chỉ khi bạn đặt màu nền, bạn sẽ nhìn thấy nó.
Aleksander

2
KHÔNG LÀM VIỆC CHO TÔI.
Markus

4
FYI Tôi ban đầu nhìn thấy cùng một vấn đề mà các nhà bình luận khác đang nhìn thấy nơi bóng của BaseView không hiển thị khi màu nền rõ ràng. Vấn đề là tôi chỉ chạy phần đầu tiên của mã (công cụ cơ sở). Khi tôi thêm BorderView dưới dạng một khung nhìn phụ, bóng bắt đầu hiển thị. Có vẻ như để bóng tối hiển thị, phải có ít nhất một đường viền (hoặc nền) có thể nhìn thấy trong cấu trúc phân cấp xem của nó. Vì vậy, hãy chắc chắn có BorderView.layer.borderWidth> = 0 với BorderView.layer.borderColor (hoặc màu nền không trong suốt)
Mike Vosseller

79

Một cách để làm điều này là đặt chế độ xem với các góc được làm tròn trong chế độ xem với bóng đổ.

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];

Sau đó, bạn có thể thêm ShadowView bất cứ nơi nào bạn muốn.


5
Amit, bạn phải đặt maskToBound / clipToBound = CÓ cho * roundView *. KHÔNG đặt cái này vào ShadowView. Tôi chưa thử mã ở trên nhưng biết chắc rằng giải pháp này chắc chắn hoạt động mặc dù không lý tưởng. ShadowRadius cao hơn sẽ chăm sóc các khu vực bán kính góc. Đặt ShadowRadius thành 0 hoặc 1 và bạn sẽ nhận thấy những gì tôi đang cố gắng nói.
Deepak GM

2
Một cái gì đó như ShadowView.layer.shadowOpacity = 0,6; mất tích
Bo.

3
"ShadowView.layer.opacity = 1.0" phải là "ShadowView.layer.shadowOpacity = 1.0"
Chris

Hoạt động trên iOS 9 nếu sử dụng ShadowView.layer.shadowOpacity = 1.0
Mansurov Ruslan

Mã được sửa cho ShadowOpacity
Softlion

63

Kiểm tra dự án ví dụ trên GitHub để đảm bảo bạn sử dụng thành phần chính xác.

Giải pháp Swift 5 đơn giản mà không cần bất kỳ cuộc phỏng vấn bổ sung hoặc phân lớp:

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
    }
}

Lưu ý rằng bạn nên thiết lập chế độ xem với bán kính góc và các thuộc tính khác trước khi gọi addShadow .

Sau đó, chỉ cần gọi nó từ viewDidLoadnhư thế này:

button.addShadow(offset: CGSize.init(width: 0, height: 3), color: UIColor.black, radius: 2.0, opacity: 0.35)

Kết quả cuối cùng:

kết quả

Siêu dễ dàng và đơn giản!


Điều này có hoạt động trên các nút? Bởi vì nó không hoạt động vào cuối của tôi.
Cesare

Tôi đã thử làm theo các bước chính xác mà bạn đề xuất. Nhưng vẫn không gặp may. Sẽ thật tuyệt nếu bạn chia sẻ một mẫu (trên Github) để xem bạn đã làm như thế nào mà dường như là không thể đối với tôi và những người khác.
Hemang

Quản lý để làm cho nó hoạt động chỉ bằng cách loại bỏ dòng này layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath. Không thể giải thích tại sao mặc dù, ai đó có một lời giải thích cho điều đó?
trupin

@Curnelious cảm thấy thoải mái khi xem câu trả lời được cập nhật với ví dụ về dự án Xcode. Nó không thể hoạt động :)
Sergey Grischyov

3
Điều này cũng có hiệu quả đối với tôi, chỉ cần một điều nữa là làm cho tất cả các màu nền của cuộc phỏng vấn phải rõ ràng để chỉ có chế độ xem container có nền có thể nhìn thấy và điều này đã giải quyết vấn đề của tôi. Cảm ơn!! @SergeyGrischyov
Rishabh

42

Điều này làm việc cho tôi. Thủ thuật là để chuyển màu nền từ chế độ xem chính sang lớp.

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 ;

Mặc dù tất cả các giải pháp khác đều hoạt động, và có lẽ chúng chung chung hơn, nhưng đây là giải pháp tốt nhất cho vấn đề. Thêm các cuộc phỏng vấn hoặc lớp con tạo ra một thế giới hoặc nỗi đau khi cố gắng duy trì kích thước khung hình, hoặc, tốt nhất, có thể gây ra các vấn đề về hiệu suất.
emem

Đây nên là câu trả lời. Sạch sẽ và thanh lịch.
Axy

Giải pháp tốt nhất và chắc chắn thanh lịch!
Roberto Ferraz

Wow, điều này thực sự hoạt động. Tôi không hiểu tại sao nó nên hoạt động - bạn nghĩ nền của chế độ xem đúng màu sẽ trực tiếp ánh xạ tới thuộc tính layer.backgroundColor trên iOS - nhưng nó LÀM VIỆC. (Xcode 8, Swift 3.) Hoàn thành tốt và cảm ơn. Đây phải là câu trả lời được chấp nhận.
Womble

Tôi đã tạo phiên bản Swift 3.1 cho câu trả lời của bạn bằng cách sử dụng UIView extensiontại đây - stackoverflow.com/a/43295741/1313939 cảm ơn vì nguồn cảm hứng!
Serge Grischyov

26

Tôi đã giải quyết vấn đề bằng cách sử dụng thủ thuật sau khi gán đường dẫn bóng cho chế độ xem container:

[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]

Lưu ý rằng đường dẫn được tạo cho bóng là một hình chữ nhật tròn có cùng bán kính góc với nền mà ô chứa:

//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]];

Câu trả lời tốt nhất bởi vì nó giải thích đúng cách để thêm bóng vào chế độ xem góc tròn hơn. Cảm ơn @Alex Stone
lập trình viên

17

Nếu bạn đang vật lộn vì làm tròn cornersso subviewsvới so với masksToBounds, thì hãy thử sử dụng chức năng của tôi:

- (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;
}

gọi nó trên quan điểm của bạn. cho dù chế độ xem của bạn có các góc tròn, bất kể kích thước, hình dạng của nó - một bóng đẹp sẽ được vẽ.

Chỉ cần giữ giá trị trả về của hàm để bạn có thể tham chiếu đến nó khi bạn muốn xóa bảng (hoặc sử dụng ví dụ insertSubview:aboveView:)


nó hoạt động tốt. Nhưng nếu chế độ xem có nhận dạng cử chỉ, thì nó sẽ không hoạt động. Làm thế nào chúng ta có thể giải quyết nó?
manujmv

@manujmv Bạn có thấy các dòng trong đó "// Sửa đổi điều này nếu cần" được chỉ định không? Đó là những gì bạn cần. bóng tối.userInteractionEnables = CÓ;
daniel.gindi

@manujmv sau đó bạn nên kiểm tra các khung của chế độ xem và xem phụ để xem tại sao. một cái gì đó có lẽ không phải ở đó mã chính xác này hoạt động với tôi trong một số ứng dụng rất hay
daniel.gindi

2
Giải pháp này hoạt động tuyệt vời cho UITableViews với các góc tròn. Ước gì tôi có thể cho nó nhiều phiếu hơn. Cảm ơn!
Chris Hart

@ CarlosEduardoLópez Bạn có thấy shadow.userInteractionEnabled = NO; // Modify this if neededdòng này không? Vì vậy, đây là trường hợp cần thiết. userInteractionEnabledlà một tài sản cơ bản và phổ biến mà bạn đã quen thuộc với :-)
daniel.gindi

12

Sử dụng Swift 4 và Xcode 9 , đây là một ví dụ hoạt động về làm tròn số ImageViewvới bóng đổ và đường viền.

    //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)

nhập mô tả hình ảnh ở đây

Nếu bạn muốn hình ảnh được hình tròn: (và hiển thị không có viền)

let cornerRadius = imageWidth / 2

nhập mô tả hình ảnh ở đây


7

Tôi đã tạo một người trợ giúp trên UIView

@interface UIView (Helper)

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset;
@end

bạn có thể gọi nó như thế này

[self.view roundCornerswithRadius:5 andShadowOffset:5];

Đây là việc thực hiện

- (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];

}

2
Đây là một giải pháp thanh lịch tốt. Đảm bảo rằng chế độ xem của bạn đã được thêm vào giám sát trước khi sử dụng. Tôi đã thêm một số tham số để giúp tôi kiểm soát bóng nhiều hơn, nhưng tổng thể hoạt động hoàn hảo. Cảm ơn!
Aaron Vegh

Đây là một giải pháp tốt nhưng nó không hoạt động với tính năng tự động thanh toán: chế độ xem sẽ được rút ra từ nguồn gốc 0,0
gderaco

5

Sau một ngày nghiên cứu về chế độ xem góc tròn với bóng, tôi rất vui khi đăng lớp uiview tùy chỉnh của mình ở đây, hy vọng kết thúc câu hỏi này:

RoundC CornerShadowView.h

#import <UIKit/UIKit.h>

@interface RoundCornerShadowView : UIView

@end

RoundC CornerShadowView.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

vì vậy, KHÔNG cần phải thêm chế độ xem trong chế độ xem hoặc bên dưới trong chế độ xem mục tiêu, chỉ cần thêm một lớp trong chế độ xem hiện tại và thực hiện 3 bước để hoàn thành nó!

hãy xem xét kỹ các ý kiến ​​trong mã, thật hữu ích khi hiểu thành phần này!


5

Một cái gì đó nhanh chóng được thử nghiệm trong 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
        }
    }
}

Sản xuất

nhập mô tả hình ảnh ở đây

Nếu bạn kích hoạt nó trong Thanh tra như thế này:

nhập mô tả hình ảnh ở đây

Nó sẽ thêm thuộc tính thời gian chạy do người dùng xác định, dẫn đến:

nhập mô tả hình ảnh ở đây

(Tôi đã thêm trước đó cornerRadius = 8)

:)


5

Bạn cần sử dụng shadowViewroundView

nhập mô tả hình ảnh ở đây

bóng tối

  • Phải có màu nền
  • Nên nằm phía sau roundView
  • Bí quyết là bố trí shadowViewmột chút bên trong, và bóng của nó cần phát sáng. Điều chỉnh insetssao cho shadowViewhoàn toàn vô hình phía sauroundView

roundView

  • Phải quay clip

Mật mã

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
}

Hoặc bạn chỉ có thể làm dưới đây mà không cần chỉ định clipToBounds/maskToBounds

layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.8

4

Giải pháp Swift 3 & IBInspectable:
Lấy cảm hứng từ giải pháp của Ade

Đầu tiên, tạo một phần mở rộng 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
          }
     }
}

Sau đó, chỉ cần chọn UIView của bạn trong chế độ xây dựng giao diện BẬTbán kính góc , như bên dưới:

Chọn UIView của bạn

Đặt bóng ON và bán kính góc

Kết quả!

Kết quả


Giống như mọi "giải pháp" khác trong chuỗi này, đơn giản là nó không hoạt động, ít nhất là không có trên iOS 11.0 / Swift 4.1.
inexcitus

Bạn đã đọc "Swift 3" khi bắt đầu chuỗi chưa? Vì vậy, điều đó có nghĩa là đó là giải pháp Swift 3, tôi đã không thử nghiệm nó trong Swift 4.1 vì tôi không cần nó nữa. Hãy chỉnh sửa câu trả lời và đưa ra giải pháp. ;) Chúc mừng
Thomás Calmon

3

Đây là giải pháp cho vấn đề xung đột maskToBound, nó hoạt động với tôi.

Sau khi bạn đặt corderRadius / BorderColor / bóng, v.v., đặt maskToBound là NO:

v.layer.masksToBounds = NO;

Điều này làm việc cho tôi !! omg tôi gần như đã làm tất cả các thủ thuật trên bạn trả lời! cảm ơn Shaopeng.
MontDeska

3

Bóng + Biên giới + Bán kính góc nhập mô tả hình ảnh ở đây

    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];

3

Đây là phiên bản của tôi trong Swift 3 cho một UIView

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)

3

Swift 4: Tạo lớp con của 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
    }

}

Sử dụng ..

Sử dụng Chế độ xem lớp


2

Chà, nếu bạn không muốn thay đổi ngòi của mình và xem hệ thống phân cấp như đề xuất David C. phương pháp này sẽ làm điều đó cho bạn. Để thêm các góc tròn và bóng cho UIImageView của bạn, chỉ cần sử dụng phương pháp này, ví dụ:

[Utils roundCornersForImageView:myImageView withCornerRadius:6.0 
andShadowOffset:2.0];

(!) Vì lý do hiệu suất, tôi không nghĩ nên sử dụng mã này trong một cái gì đó như UITableView, vì mã này thay đổi phân cấp xem. Vì vậy, tôi sẽ đề nghị thay đổi ngòi của bạn và thêm chế độ xem cho hiệu ứng bóng và sử dụng mã Davic 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];   
}    

2

Chủ đề cũ vẫn còn hiện tại ...

Tôi đã chỉnh sửa phương pháp của Daniel Gindi để có thể sử dụng nó với các nút, v.v. Nếu bất cứ ai cần các góc tròn hoặc muốn kết hợp các góc tròn và đường viền thì nó phải được đặt trên lớp của khung nhìn được truyền cho phương thức này. Tôi cũng đã thiết lập rasterization để tăng tốc một chút.

+ (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;
}

2

Phần sau hoạt động tốt nhất với tôi (mã này nằm trong phần mở rộng UIView, vì vậy tự biểu thị một số UIView mà chúng ta phải thêm một bóng và góc tròn)

- (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];
}

Sự khác biệt chính giữa mẫu này và các mẫu mã khác là cái này thêm chế độ xem bóng dưới dạng chế độ xem anh chị em (so với việc thêm chế độ xem hiện tại dưới dạng xem dưới dạng xem bóng), do đó loại bỏ sự cần thiết phải sửa đổi phân cấp chế độ xem hiện tại theo bất kỳ cách nào.


1

câu trả lời của daniel.gindi ở trên đã lừa tôi! (+1 daniel) Tuy nhiên, tôi đã phải thực hiện các điều chỉnh nhỏ - thay đổi kích thước ShadowFrame thành kích thước khung hình của chế độ xem và cho phép tương tác người dùng. Đây là mã được cập nhật:

+ (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;
}

Tôi muốn thêm rằng trong trường hợp của tôi, tôi đã cố gắng thêm nó vào bộ điều khiển xem của bên thứ 3, tức là tôi không có quyền kiểm soát trực tiếp đối với mã. Vì vậy, đây là cách tôi sử dụng chức năng trên:

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;

1

Tôi thực hiện một số thay đổi đối với mã của daniel.gindi

Đây là tất cả những gì bạn cần để làm cho nó hoạt động.

+ (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];
}

1

Bạn cần sử dụng hai UIViewsđể đạt được điều này. Một cái UIViewsẽ hoạt động như bóng và cái khác sẽ hoạt động cho đường viền tròn.

Đây là đoạn mã a Class Methodvới sự trợ giúp của 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;
}

Trong đoạn mã trên btnCompose_click:sẽ trở thành một @requiredphương thức ủy nhiệm sẽ kích hoạt vào nút bấm.

Và ở đây tôi đã thêm một nút vào UIViewControllernhư thế này:

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];

Kết quả sẽ như thế này:

nhập mô tả hình ảnh ở đây


1

Tôi đã thử rất nhiều giải pháp từ bài đăng này và kết thúc với giải pháp dưới đây. Đây là giải pháp bằng chứng đầy đủ trừ khi bạn cần thả bóng trên chế độ xem màu rõ ràng .

- (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;
}

Biểu hiện là "bằng chứng ngu ngốc". :)
Ben Thomas

Tôi chỉ sửa tiếng Anh. :) Giải pháp hoạt động.
Ben Thomas

1

Đây là giải pháp sẽ làm việc chắc chắn!

Tôi đã tạo tiện ích mở rộng UIView với các cạnh cần thiết để áp dụng bóng như bên dưới


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)    {

        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 = self.frame.size.height / 2
        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
    }
}

Cuối cùng, bạn có thể gọi hàm bóng như bên dưới cho bất kỳ lớp con UIView nào, bạn cũng có thể chỉ định cạnh để áp dụng bóng trên, thử các biến thể khác nhau theo nhu cầu thay đổi tham số của lệnh gọi phương thức bên dưới.

viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)

Hình ảnh kết quả

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


0

Câu trả lời được cung cấp bởi Evan Mulawski sẽ hoạt động hoàn hảo. Điều hấp dẫn là bạn phải đặt màu nền cho chế độ xem thành ClearColor và thuộc tính maskToBound thành NO.

Bạn có thể đặt bất kỳ màu nào bạn muốn cho chế độ xem, đặt nó như thế nào

v.layer.backgroundColor = your color;

Hi vọng điêu nay co ich..


0

Đây là cách bạn làm điều đó, với các góc tròn và bóng tròn mà không bận tâm đến các đường dẫn.

//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];

Khung nhìn với nội dung, trong trường hợp của tôi là UIImageView, có bán kính góc và do đó phải che đi các giới hạn.

Chúng tôi tạo một chế độ xem có kích thước bằng nhau khác cho các bóng, đặt mặt nạ của nó thành NO và sau đó thêm chế độ xem nội dung vào chế độ xem vùng chứa (ví dụ: ShadowContainer).


0

Tôi viết phương pháp thể loại UIView này để giải quyết vấn đề này, sử dụng các chế độ xem riêng cho bóng và bán kính góc.

-(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;
}

0

Giải pháp Swift 4 để tạo vòng UICollectionViewCell và thêm Shadows , không có bất kỳ tiện ích mở rộng và biến chứng nào :)

Lưu ý: Đối với các chế độ xem đơn giản, ví dụ: Nút. Xem câu trả lời của @ suragch trong bài viết này. https://stackoverflow.com/a/34984063/7698092 . Đã thử nghiệm thành công cho các nút

Trong trường hợp nếu bất kỳ ai vẫn cố gắng làm tròn các góc và thêm bóng cùng một lúc. Mặc dù giải pháp này hoạt động với UICollectionViewCell, nó có thể được khái quát hóa cho bất kỳ chế độ xem nào.

Kỹ thuật này làm việc cho tôi mà không thực hiện bất kỳ phần mở rộng và tất cả những thứ phức tạp. Tôi đang làm việc với StoryBoard.

Kỹ thuật

Bạn phải thêm một UIView (giả sử là "containerView") bên trong UICollectionViewCell của bạn trong StoryBoard và thêm tất cả các chế độ xem được yêu cầu (các nút, hình ảnh, v.v.) trong containerView này. Xem ảnh chụp màn hình. Cấu trúc của tế bào

Kết nối ổ cắm cho containerView. Thêm các dòng mã sau trong hàm ủy nhiệm 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

Đầu ra

Xem ảnh chụp màn hình giả lập Các góc được làm tròn với Shadows (UICollectionViewCell)


0
extension UIView {
    func dropRoundedShadowForAllSides() {
        let backgroundView = UIView(frame:self.frame)
        let radius = frame.height/2
        backgroundView.layer.masksToBounds = false
        self.layer.masksToBounds = true
        backgroundView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        backgroundView.layer.shadowRadius = 4
        backgroundView.layer.shadowOpacity = 0.4

        let path = UIBezierPath()

        // Start at the Top Left Corner + radius distance
        path.move(to: CGPoint(x: 2*radius, y: 0.0))

        // Move to the Top Right Corner - radius distance
        path.addLine(to: CGPoint(x: backgroundView.frame.size.width - radius, y: 0.0))

        // Move to top right corner + radius down as curve
        let centerPoint1 = CGPoint(x:backgroundView.frame.size.width - radius,y:radius)
        path.addArc(withCenter: centerPoint1, radius: radius, startAngle: 3*(.pi/2), endAngle: 0, clockwise: true)

        // Move to the Bottom Right Corner - radius
        path.addLine(to: CGPoint(x: backgroundView.frame.size.width, y: backgroundView.frame.size.height - radius))

        // Move to top right corner + radius left as curve
        let centerPoint2 = CGPoint(x:backgroundView.frame.size.width - radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint2, radius: radius, startAngle: 0, endAngle: .pi/2, clockwise: true)

        // Move to the Bottom Left Corner - radius
        path.addLine(to: CGPoint(x: radius, y: backgroundView.frame.size.height))

        // Move to left right corner - radius up as curve
        let centerPoint3 = CGPoint(x:radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint3, radius: radius, startAngle: .pi/2, endAngle: .pi, clockwise: true)

        // Move to the top Left Corner - radius
        path.addLine(to: CGPoint(x: 0, y: radius))

        // Move to top right corner + radius down as curve
        let centerPoint4 = CGPoint(x:radius,y:radius)
        path.addArc(withCenter: centerPoint4, radius: radius, startAngle: .pi, endAngle: 3 * (.pi/2), clockwise: true)

        path.close()

        backgroundView.layer.shadowPath = path.cgPath
        if let superView = self.superview {
            superView.addSubview(backgroundView)
            superView.sendSubview(toBack: backgroundView)
            superView.bringSubview(toFront: self)
        }

    }
}

Xin chào, cảm ơn câu trả lời của bạn, bạn nên thêm một số nhận xét vào mã của mình để giải thích một chút như được mô tả trong Cách trả lời .
Baptiste Mille-Mathias
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.