屏蔽 UIView 和自动布局
Masking a UIView and Auto Layout
我有一个 UIView,我想用另一个 UIView 遮盖,在它的中心打一个洞。这是我的 viewDidLoad
:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.viewToMask];
[self.view addSubview:self.theMask];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.viewToMask attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.viewToMask attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[cyan(200)]" options:0 metrics:nil views:@{@"cyan": self.viewToMask}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[cyan(200)]" options:0 metrics:nil views:@{@"cyan": self.viewToMask}]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.theMask attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.viewToMask attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.theMask attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.viewToMask attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[mask(100)]" options:0 metrics:nil views:@{@"mask": self.theMask}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[mask(100)]" options:0 metrics:nil views:@{@"mask": self.theMask}]];
}
它给了我想要的东西,减去掩蔽:
如果我再添加一行:
[self.viewToMask setMaskView:self.theMask];
两个视图都消失了 --- 小视图 (self.theMask
) 掩盖了整个大视图 (self.viewToMask
),即使它只有一半大小。有谁知道这里发生了什么?可以不使用 UIView.maskView
和自动布局吗?
正如 Zev 所解释的,遮罩视图存在于普通视图层次结构之外,因此不能与自动布局一起使用。我通过将它手动放置在我的视图控制器的 viewDidLayoutSubviews
:
中解决了这个问题
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
CGRect viewToMaskRect = self.viewToMask.bounds;
CGRect maskRect = CGRectMake(viewToMaskRect.origin.x + 50.0, viewToMaskRect.origin.y + 50.0, 100.0, 100.0);
[self.theMask setFrame:maskRect];
[self.viewToMask setMaskView:self.theMask];
}
您可以通过将 maskView 设为普通子视图(例如,在具有相关约束的故事板中)然后仅在 viewWillLayoutSubviews 中将其设置为 maskView 来使自动布局与您的 maskView 一起工作。即:
-(void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.viewToBeMasked.maskView = self.maskViewWithLayoutConstraints;
}
根据 Russ'
的回答,我进行了自己的研究并找到了替代解决方法。
下面的代码示例将用 10pt 遮盖主视图的左侧和右侧。重要
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
self.setupMaskView()
}
private func setupMaskView() {
let maskView = UIView()
maskView.translatesAutoresizingMaskIntoConstraints = false
maskView.backgroundColor = UIColor(white: 0.0, alpha: 1.0)
let maskContainerView = UIView()
maskContainerView.addSubview(maskView)
self.view.addSubview(maskContainerView)
maskView.leftAnchor.constraintEqualToAnchor(self.view.leftAnchor, constant: 10).active = true
maskView.widthAnchor.constraintEqualToAnchor(self.view.widthAnchor, constant: -20).active = true
maskView.heightAnchor.constraintEqualToAnchor(self.view.heightAnchor).active = true
self.view.maskView = maskContainerView // this will not work it we place this line above the constraint code !!!
/* I have no idea why this does not work and why nesting is required, maybe some sort of bug? */
}
}
此代码使用 iOS 9.0 和 Swift 2.0 中可用的 AutoLayout 语法。 (写于Xcode 7 beta 4)
我有一个 UIView,我想用另一个 UIView 遮盖,在它的中心打一个洞。这是我的 viewDidLoad
:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.viewToMask];
[self.view addSubview:self.theMask];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.viewToMask attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.viewToMask attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[cyan(200)]" options:0 metrics:nil views:@{@"cyan": self.viewToMask}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[cyan(200)]" options:0 metrics:nil views:@{@"cyan": self.viewToMask}]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.theMask attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.viewToMask attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.theMask attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.viewToMask attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[mask(100)]" options:0 metrics:nil views:@{@"mask": self.theMask}]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[mask(100)]" options:0 metrics:nil views:@{@"mask": self.theMask}]];
}
它给了我想要的东西,减去掩蔽:
如果我再添加一行:
[self.viewToMask setMaskView:self.theMask];
两个视图都消失了 --- 小视图 (self.theMask
) 掩盖了整个大视图 (self.viewToMask
),即使它只有一半大小。有谁知道这里发生了什么?可以不使用 UIView.maskView
和自动布局吗?
正如 Zev 所解释的,遮罩视图存在于普通视图层次结构之外,因此不能与自动布局一起使用。我通过将它手动放置在我的视图控制器的 viewDidLayoutSubviews
:
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
CGRect viewToMaskRect = self.viewToMask.bounds;
CGRect maskRect = CGRectMake(viewToMaskRect.origin.x + 50.0, viewToMaskRect.origin.y + 50.0, 100.0, 100.0);
[self.theMask setFrame:maskRect];
[self.viewToMask setMaskView:self.theMask];
}
您可以通过将 maskView 设为普通子视图(例如,在具有相关约束的故事板中)然后仅在 viewWillLayoutSubviews 中将其设置为 maskView 来使自动布局与您的 maskView 一起工作。即:
-(void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.viewToBeMasked.maskView = self.maskViewWithLayoutConstraints;
}
根据 Russ'
的回答,我进行了自己的研究并找到了替代解决方法。
下面的代码示例将用 10pt 遮盖主视图的左侧和右侧。重要
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
self.setupMaskView()
}
private func setupMaskView() {
let maskView = UIView()
maskView.translatesAutoresizingMaskIntoConstraints = false
maskView.backgroundColor = UIColor(white: 0.0, alpha: 1.0)
let maskContainerView = UIView()
maskContainerView.addSubview(maskView)
self.view.addSubview(maskContainerView)
maskView.leftAnchor.constraintEqualToAnchor(self.view.leftAnchor, constant: 10).active = true
maskView.widthAnchor.constraintEqualToAnchor(self.view.widthAnchor, constant: -20).active = true
maskView.heightAnchor.constraintEqualToAnchor(self.view.heightAnchor).active = true
self.view.maskView = maskContainerView // this will not work it we place this line above the constraint code !!!
/* I have no idea why this does not work and why nesting is required, maybe some sort of bug? */
}
}
此代码使用 iOS 9.0 和 Swift 2.0 中可用的 AutoLayout 语法。 (写于Xcode 7 beta 4)