こんにちは私は、UIVisualEffectViewで角の半径を設定することが可能かどうか疑問に思っていますか?これが私が試したコードです:
@IBOutlet var blurView: UIVisualEffectView!
var blurLayer : CALayer{
return blurView.layer
}
override func viewDidLoad() {
super.viewDidLoad()
setUpLayer()
// Do any additional setup after loading the view.
}
func setUpLayer(){
blurLayer.cornerRadius = 50
}
そして
@IBOutlet var blurView: UIVisualEffectView!
override func viewDidLoad() {
super.viewDidLoad()
blurView.layer.cornerRadius = 50
// Do any additional setup after loading the view.
}
それらのどれも動作しません。
@theMonsterの提案の後に、コメントを投稿します。
override func viewDidLoad() {
super.viewDidLoad()
blurView.layer.cornerRadius = 50
blurView.clipsToBounds = true
}
ストーリーボードで、ユーザー定義のランタイム属性に2つのパラメーターを追加しますlayer.cornerRadius = 8
およびlayer.masksToBounds = true
またはコードで
@IBOutlet var blurView: UIVisualEffectView! {
didSet {
blurView.layer.cornerRadius = 8
blurView.layer.masksToBounds = true
}
}
既存のソリューションはすべて完璧ではありません。
UIVisualEffectView
は、2つのサブビューコンテンツを合成することで視覚効果を実装します。1つは背景ビューで、もう1つはフィルタービューです。UIVisualEffectView
全体をマスクしてコーナー半径を実装すると、角の周りに汚れた色がある。
これらの汚れた色を取り除くには、UIVisualEffectsのフィルタービューをマスクするだけです。
private typealias ObjcRawUIVisualEffectViewSelCGRect =
@convention(c) (UIVisualEffectView, Selector, CGRect) -> Void
private var cornerRadiusKey =
"com.WeZZard.Waxing.UIVisualEffectView-CornerRadius.cornerRadius"
private var needsUpdateMaskLayerKey =
"com.WeZZard.Waxing.UIVisualEffectView-CornerRadius.needsUpdateMaskLayer"
extension UIVisualEffectView {
public var cornerRadius: CGFloat {
get {
if let storedValue = objc_getAssociatedObject(self,
&cornerRadiusKey)
as? CGFloat
{
return storedValue
}
return 0
}
set {
if cornerRadius != newValue {
objc_setAssociatedObject(self,
&cornerRadiusKey,
newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
setNeedsUpdateMaskLayer()
}
}
}
private var needsUpdateMaskLayer: Bool {
get {
if let storedValue = objc_getAssociatedObject(self,
&needsUpdateMaskLayerKey)
as? Bool
{
return storedValue
}
return false
}
set {
objc_setAssociatedObject(self,
&needsUpdateMaskLayerKey,
newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public override class func initialize() {
swizzle_setBounds()
}
private class func swizzle_setBounds() {
struct Static {
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
let selector: Selector = "setBounds:"
let method = class_getInstanceMethod(self, selector)
let imp_original = method_getImplementation(method)
before_setBounds = unsafeBitCast(imp_original,
ObjcRawUIVisualEffectViewSelCGRect.self)
class_replaceMethod(self,
selector,
unsafeBitCast(after_setBounds, IMP.self),
"@:{_struct=CGRect}")
}
}
private func setNeedsUpdateMaskLayer() {
needsUpdateMaskLayer = true
NSOperationQueue.mainQueue().addOperationWithBlock { [weak self] _ in
self?.updateMaskLayerIfNeeded()
}
}
private func updateMaskLayerIfNeeded() {
if needsUpdateMaskLayer {
updateMaskLayer()
needsUpdateMaskLayer = false
}
}
private func updateMaskLayer(){
var filterViewFound = false
for each in subviews {
if each.dynamicType.description()
.containsString("Filter")
{
filterViewFound = true
let newPath = UIBezierPath(roundedRect: each.bounds,
cornerRadius: self.cornerRadius)
.CGPath
if let existedMask = each.layer.mask
as? CAShapeLayer
{
existedMask.path = newPath
} else {
let shapeLayer = CAShapeLayer()
shapeLayer.path = newPath
each.layer.mask = shapeLayer
}
} else {
setNeedsUpdateMaskLayer()
}
}
assert(filterViewFound == true, "Filter view was not found! Check your hacking!")
}
}
private var before_setBounds: ObjcRawUIVisualEffectViewSelCGRect = { _ in
fatalError("No implementation found")
}
private let after_setBounds: ObjcRawUIVisualEffectViewSelCGRect = {
(aSelf, selector, bounds) -> Void in
let oldBounds = aSelf.bounds
before_setBounds(aSelf, selector, bounds)
if oldBounds.size != bounds.size {
aSelf.setNeedsUpdateMaskLayer()
}
}
そして、すべてが完了しました!
サブクラスUIVisualEffectView
class PSORoundedVisualEffectView : UIVisualEffectView{
override func layoutSubviews() {
super.layoutSubviews()
updateMaskLayer()
}
func updateMaskLayer(){
let shapeLayer = CAShapeLayer()
shapeLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 10).CGPath
self.layer.mask = shapeLayer
}
}
UIBezierPathを任意の形状に置き換えます。