ULa*_*ins 12 objective-c nsview autolayout
我想NSView在保持约束的同时将一个替换为另一个视图.
我有一个superview,subview因为它的孩子和placeholder我正计划搬到subview的地方.但它似乎是代码
[[superview] replaceSubview:subview with:placeholder];
Run Code Online (Sandbox Code Playgroud)
删除所有与之相关的约束subview并导致只删除subview.
如何将约束从一个视图"复制"到另一个视图?
Bra*_*red 12
这是我很久以前写的一些代码,用来做你要求的.
我的代码用于在同一个superview中交换两个NSView,但是您可以通过剥离不需要的位并按照谨慎的顺序添加和删除视图/约束来轻松地对其进行修改以进行替换.事实上,我在"代理"视图控制器类中有一个较短版本的代码,它完全符合你的要求,但我不能分享它,因为它是一个不属于我的专有项目.
我将告诉您,您需要做的是将约束从代理视图复制到新视图,然后将新视图添加到superview.之后,将代理的超级视图约束复制到新视图,并且只有在执行此操作后才从超级视图中删除代理视图.
- (void)swapView:(NSView*) source withView:(NSView*) dest persist:(BOOL) persist
{
NSLog(@"swapping %@ with %@", source.identifier, dest.identifier);
// !!!: adjust the "Auto Layout" constraints for the superview.
// otherwise changing the frames is impossible. (instant reversion)
// we could disable "Auto Layout", but let's try for compatibility
// TODO: we need to either enforce that the 2 controls have the same superview
// before accepting the drag operation
// or modify this code to take two diffrent superviews into account
// we are altering the constraints so iterate a copy!
NSArray* constraints = [dest.superview.constraints copy];
for (NSLayoutConstraint* constraint in constraints) {
id first = constraint.firstItem;
id second = constraint.secondItem;
id newFirst = first;
id newSecond = second;
BOOL match = NO;
if (first == dest) {
newFirst = source;
match = YES;
}
if (second == dest) {
newSecond = source;
match = YES;
}
if (first == source) {
newFirst = dest;
match = YES;
}
if (second == source) {
newSecond = dest;
match = YES;
}
if (match && newFirst) {
[dest.superview removeConstraint:constraint];
@try {
NSLayoutConstraint* newConstraint = nil;
newConstraint = [NSLayoutConstraint constraintWithItem:newFirst
attribute:constraint.firstAttribute
relatedBy:constraint.relation
toItem:newSecond
attribute:constraint.secondAttribute
multiplier:constraint.multiplier
constant:constraint.constant];
newConstraint.shouldBeArchived = constraint.shouldBeArchived;
newConstraint.priority = NSLayoutPriorityWindowSizeStayPut;
[dest.superview addConstraint:newConstraint];
}
@catch (NSException *exception) {
NSLog(@"Constraint exception: %@\nFor constraint: %@", exception, constraint);
}
}
}
[constraints release];
NSMutableArray* newSourceConstraints = [NSMutableArray array];
NSMutableArray* newDestConstraints = [NSMutableArray array];
// again we need a copy since we will be altering the original
constraints = [source.constraints copy];
for (NSLayoutConstraint* constraint in constraints) {
// WARNING: do not tamper with intrinsic layout constraints
if ([constraint class] == [NSLayoutConstraint class]
&& constraint.firstItem == source) {
// this is a source constraint. we need to copy it to the destination.
NSLayoutConstraint* newConstraint = nil;
newConstraint = [NSLayoutConstraint constraintWithItem:dest
attribute:constraint.firstAttribute
relatedBy:constraint.relation
toItem:constraint.secondItem
attribute:constraint.secondAttribute
multiplier:constraint.multiplier
constant:constraint.constant];
newConstraint.shouldBeArchived = constraint.shouldBeArchived;
[newDestConstraints addObject:newConstraint];
[source removeConstraint:constraint];
}
}
[constraints release];
// again we need a copy since we will be altering the original
constraints = [dest.constraints copy];
for (NSLayoutConstraint* constraint in constraints) {
// WARNING: do not tamper with intrinsic layout constraints
if ([constraint class] == [NSLayoutConstraint class]
&& constraint.firstItem == dest) {
// this is a destination constraint. we need to copy it to the source.
NSLayoutConstraint* newConstraint = nil;
newConstraint = [NSLayoutConstraint constraintWithItem:source
attribute:constraint.firstAttribute
relatedBy:constraint.relation
toItem:constraint.secondItem
attribute:constraint.secondAttribute
multiplier:constraint.multiplier
constant:constraint.constant];
newConstraint.shouldBeArchived = constraint.shouldBeArchived;
[newSourceConstraints addObject:newConstraint];
[dest removeConstraint:constraint];
}
}
[constraints release];
[dest addConstraints:newDestConstraints];
[source addConstraints:newSourceConstraints];
// auto layout makes setting the frame unnecissary, but
// we do it because its possible that a module is not using auto layout
NSRect srcRect = source.frame;
NSRect dstRect = dest.frame;
// round the coordinates!!!
// otherwise we will have problems with persistant values
srcRect.origin.x = round(srcRect.origin.x);
srcRect.origin.y = round(srcRect.origin.y);
dstRect.origin.x = round(dstRect.origin.x);
dstRect.origin.y = round(dstRect.origin.y);
source.frame = dstRect;
dest.frame = srcRect;
if (persist) {
NSString* rectString = NSStringFromRect(srcRect);
[[_theme prefrences] setObject:rectString forKey:dest.identifier];
rectString = NSStringFromRect(dstRect);
[[_theme prefrences] setObject:rectString forKey:source.identifier];
}
}
Run Code Online (Sandbox Code Playgroud)
你可以放心地忽略你想象中的持久性.在我的情况下,我想实现iOS跳板功能(能够点按并按住按钮,它摇晃,让我将它拖到另一个按钮并交换位置,同时在启动之间保持不变)
| 归档时间: |
|
| 查看次数: |
4770 次 |
| 最近记录: |