Невозможно добавить угловой радиус и тень
Я пытаюсь нарисовать тень и угол радиуса на изображении. Я могу добавить их отдельно, но у меня нет возможности добавить оба эффекта одновременно. Я добавляю тень с помощью:
[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];
Здесь слой является CALayer подкласса UIView. Поэтому это срабатывает, когда я устанавливаю
[layer setMasksToBounds:NO];
Теперь, чтобы добавить радиус угла, я делаю это:
[layer setCornerRadius:7.0f];
но мне нужно установить MasksToBounds в YES, чтобы это работало:
[layer setMasksToBounds:YES];
В любом случае я могу добавить оба этих эффекта?
Спасибо за ваше время,
Денис
Ответы
Ответ 1
Да, да, есть...
Если вы хотите как радиус угла, так и тень, вы не включаете -masksToBounds, а задаете радиус угла и задаете путь безье тени с закругленным прямоугольником. Держите радиус двух одинаковых:
[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];
[layer setCornerRadius:12.0f];
[layer setShadowPath:
[[UIBezierPath bezierPathWithRoundedRect:[self bounds]
cornerRadius:12.0f] CGPath]];
Вы можете проверить свою производительность без параметра -shouldRasterize после установки теневого пути. Производительность чертежа имеет тенденцию быть очень хорошей, если вы установили теневой путь.
UPDATE
Я не рассматривал эту проблему довольно долго, но, похоже, вам больше не нужно устанавливать shadowPath
, чтобы заставить это работать. Просто установка cornerRadius
и shadowOpacity
будет работать сейчас. Я думаю, что это имело место с iOS5 (насколько я могу судить). Предоставление этого обновления, вероятно, не нужно, поскольку установка этих параметров "просто работает", но я предоставил его для потомства. Чтобы повторить, это теперь все, что вам нужно:
[layer setShadowOpacity:0.4];
[layer setCornerRadius:12.0f];
Если вам по-прежнему нужна более высокая производительность, вы можете продолжить и установить параметр shouldRasterize
:
[layer setShouldRasterize:YES];
И говоря о производительности, стоит отметить, что если вы заметите вялые анимации, вы захотите использовать технику настройки пути тени в конце концов. Это обновление было действительно просто указать, что установка пути больше не требуется для достижения эффекта одновременного отображения радиуса угла и тени. Если производительность - ваш приоритет, используйте путь.
ОБНОВЛЕНИЕ 2
Поскольку у людей, похоже, не получается заставить это работать в некоторых случаях, я опубликую более полный фрагмент кода здесь из образца проекта, который я создал:
- (void)viewDidLoad
{
[super viewDidLoad];
CALayer *layer = [CALayer layer];
[layer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 200.0f)];
[layer setPosition:[[self view] center]];
[layer setBackgroundColor:[[UIColor lightGrayColor] CGColor]];
[layer setShadowOpacity:0.55f];
[layer setCornerRadius:8.0f];
[layer setBorderWidth:1.0f];
[[[self view] layer] addSublayer:layer];
[[[self testView] layer] setShadowOpacity:0.55f];
[[[self testView] layer] setShadowRadius:15.0f];
[[[self testView] layer] setCornerRadius:8.0f];
[[[self testView] layer] setBorderWidth:1.0f];
}
testView
- это UIView, который я добавил в Interface Builder и установил выход. Это делается для того, чтобы убедиться, что он работает одинаково на обоих уровнях, которые вы добавляете явно, а также на слои в рамках subviews.
Я тестировал это на симуляторах для iOS5 через iOS6.1. Это дает мне результат в каждом из них:
![enter image description here]()
Ответ 2
Следующий код Swift 3 показывает, как нарисовать тень и радиус угла на изображении, используя CAShapeLayer
и CALayer
.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// constants
let radius: CGFloat = 20, offset = 8
let rect = CGRect(x: 0, y: 0, width: 200, height: 200)
// roundedView
let roundedView = UIView()
view.addSubview(roundedView)
// shadow layer
let shadowLayer = CALayer()
shadowLayer.shadowColor = UIColor.darkGray.cgColor
shadowLayer.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath
shadowLayer.shadowOffset = CGSize(width: offset, height: offset)
shadowLayer.shadowOpacity = 0.8
shadowLayer.shadowRadius = 2
roundedView.layer.addSublayer(shadowLayer)
// mask layer
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath
// image layer
let imageLayer = CALayer()
imageLayer.mask = maskLayer
imageLayer.frame = rect
imageLayer.contentsGravity = kCAGravityResizeAspectFill
imageLayer.contents = UIImage(named: "image")?.cgImage
roundedView.layer.addSublayer(imageLayer)
// auto layout
roundedView.translatesAutoresizingMaskIntoConstraints = false
roundedView.widthAnchor.constraint(equalToConstant: rect.width).isActive = true
roundedView.heightAnchor.constraint(equalToConstant: rect.height).isActive = true
roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
Этот код генерирует следующий экран:
![введите описание изображения здесь]()
Предыдущий код может быть реорганизован в следующие быстрые файлы:
CustomView.swift
import UIKit
class CustomView: UIView {
var imageLayer: CALayer!
var image: UIImage? {
didSet { refreshImage() }
}
override var intrinsicContentSize:
CGSize {
return CGSize(width: 200, height: 200)
}
func refreshImage() {
if let imageLayer = imageLayer, let image = image {
imageLayer.contents = image.cgImage
}
}
override func layoutSubviews() {
super.layoutSubviews()
if imageLayer == nil {
let radius: CGFloat = 20, offset: CGFloat = 8
let shadowLayer = CALayer()
shadowLayer.shadowColor = UIColor.darkGray.cgColor
shadowLayer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
shadowLayer.shadowOffset = CGSize(width: offset, height: offset)
shadowLayer.shadowOpacity = 0.8
shadowLayer.shadowRadius = 2
layer.addSublayer(shadowLayer)
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
imageLayer = CALayer()
imageLayer.mask = maskLayer
imageLayer.frame = bounds
imageLayer.backgroundColor = UIColor.red.cgColor
imageLayer.contentsGravity = kCAGravityResizeAspectFill
layer.addSublayer(imageLayer)
}
refreshImage()
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let roundedView = CustomView()
roundedView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(roundedView)
// auto layout
let horizontalConstraint = roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
roundedView.image = UIImage(named: "image")
}
}
Вы можете найти больше способов комбинировать изображения с закругленными углами и тенью на этом Github repo.
Ответ 3
Поскольку я использую UIButton
с фоновым изображением, ни один из этих ответов не работал у меня. На моих пуговицах я не получаю ни тени, ни круглых краев.
Самый простой способ в моем сценарии состоял в том, чтобы просто добавить еще один вид за кнопкой и добавить к нему тень так:
button.clipsToBounds=YES;
button.layer.cornerRadius = 25;
UIView *shadowView = [[UIView alloc]initWithFrame:button.frame];
shadowView.backgroundColor = [UIColor whiteColor];//needs this to cast shadow
shadowView.layer.cornerRadius = 25;
shadowView.clipsToBounds = YES;
shadowView.layer.masksToBounds = NO;
shadowView.layer.shadowOffset = CGSizeMake(0, 2);
shadowView.layer.shadowRadius = 1;
shadowView.layer.shadowOpacity = 0.2;
[[button superview]addSubview:shadowView];
[[button superview]bringSubviewToFront:button];
Ответ 4
view.layer.cornerRadius=4;
[view.layer setMasksToBounds:YES];
[view.layer setShadowColor:SHADOW_COLOR];
[view.layer setShadowOpacity:4 ];
[view.layer setShadowRadius:4];
[view.layer setShadowOffset:0];
[view.layer setShadowPath: [[UIBezierPath bezierPathWithRoundedRect:[view bounds] cornerRadius:CORNER_RADIUS] CGPath]];
view.layer.borderColor=[[UIColor lightGrayColor] colorWithAlphaComponent:.5].CGColor;
view.layer.borderWidth=.4;