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 maskToBounds
xảy ra.
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 maskToBounds
xảy ra.
Câu trả lời:
Đ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 .
// 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
Đ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?
Chúng ta có thể thực hiện điều này với
blueView.layer.masksToBounds = true
(Ngoài ra, blueView.clipsToBounds = true
cho kết quả tương tự .)
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:
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 và ở đây cũng có.
Câu trả lời này đã được thử nghiệm với Swift 4 và Xcode 9.
baseView.backgroundColor = UIColor.clear
loại bỏ bóng. Chỉ khi bạn đặt màu nền, bạn sẽ nhìn thấy nó.
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.
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ừ viewDidLoad
như 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:
Siêu dễ dàng và đơn giản!
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 đó?
Đ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 ;
UIView extension
tại đây - stackoverflow.com/a/43295741/1313939 cảm ơn vì nguồn cảm hứng!
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]];
Nếu bạn đang vật lộn vì làm tròn corners
so subviews
vớ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:
)
shadow.userInteractionEnabled = NO; // Modify this if needed
dòng này không? Vì vậy, đây là trường hợp cần thiết. userInteractionEnabled
là một tài sản cơ bản và phổ biến mà bạn đã quen thuộc với :-)
Sử dụng Swift 4 và Xcode 9 , đây là một ví dụ hoạt động về làm tròn số ImageView
vớ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)
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
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];
}
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:
#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
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!
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
Nếu bạn kích hoạt nó trong Thanh tra như thế nà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:
(Tôi đã thêm trước đó cornerRadius = 8
)
:)
Bạn cần sử dụng shadowView
vàroundView
bóng tối
roundView
shadowView
một chút bên trong, và bóng của nó cần phát sáng. Điều chỉnh insets
sao cho shadowView
hoàn toàn vô hình phía sauroundView
roundView
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
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ẬT và bán kính góc , như bên dưới:
Kết quả!
Đâ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;
Bóng + Biên giới + Bán kính góc
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];
Đâ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)
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 ..
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];
}
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;
}
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.
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;
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];
}
Bạn cần sử dụng hai UIViews
để đạt được điều này. Một cái UIView
sẽ 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 Method
vớ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 @required
phươ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 UIViewController
như 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:
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;
}
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ả
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..
Đâ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).
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;
}
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.
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
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)
}
}
}