画像に影と角の半径を描画しようとしています。別々に追加することはできますが、両方のエフェクトを同時に追加する方法がありません。私は影を追加しています:
[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];
ここで、layerはUIViewサブクラスのCALayerです。だからこれは私が設定するたびに機能します
[layer setMasksToBounds:NO];
次に、コーナー半径を追加します。これを行います。
[layer setCornerRadius:7.0f];
ただし、これを機能させるには、MasksToBoundsをYESに設定する必要があります。
[layer setMasksToBounds:YES];
とにかく、これらの両方の効果を追加することができますか?
御時間ありがとうございます、
デニス
はい、あります...
コーナー半径とドロップシャドウの両方が必要な場合は、-masksToBoundsをオンにするのではなく、コーナー半径を設定してベジェパスを設定します。丸みを帯びた長方形の影の。 2つの半径を同じに保ちます。
[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
は、Interface Builderで追加し、アウトレットを設定したUIViewです。これは、明示的に追加した両方のレイヤーとサブビュー内のレイヤーで同じように機能することを確認するためです。
IOS5からiOS6.1のシミュレーターでこれをテストしました。それはそれらのそれぞれで私にこの結果を与えます:
次の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
}
}
このコードは、次の表示を生成します。
前のコードは、次のSwiftファイルにリファクタリングできます:
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リポジトリ 。
背景画像で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];