iOS – 使用分隔视图调整垂直视图的大小

这个问题类似于我在这里问的问题。 罗布回答我,他的代码完美的工作。 我正在尝试做同样的事情,但是让视图垂直。

这是我现在拥有的。

我的viewDidLoad

 UIView *previousContentView = nil; for (NSInteger i = 0; i < 4; i++) { UIView *contentView = [self addRandomColoredView]; [self.view.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor].active = true; [self.view.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor].active = true; if (previousContentView) { VerticalSeparatorView *view = [[VerticalSeparatorView alloc] init]; [view addSeparatorBetweenView:previousContentView secondView:contentView]; NSLayoutConstraint *width = [contentView.widthAnchor constraintEqualToAnchor:previousContentView.widthAnchor]; width.priority = 250; width.active = true; } else { [self.view.leftAnchor constraintEqualToAnchor:contentView.leftAnchor].active = true; } previousContentView = contentView; } [self.view.rightAnchor constraintEqualToAnchor:previousContentView.rightAnchor].active = true; 

在我的VerticalSeparatorView

 @implementation VerticalSeparatorView #pragma mark - Configuration /** Add a separator between views This creates the separator view; adds it to the view hierarchy; adds the constraint for height; adds the constraints for leading/trailing with respect to its superview; and adds the constraints the relation to the views above and below @param firstView The UIView above the separator @param secondView The UIView below the separator @returns The separator UIView */ - (instancetype)addSeparatorBetweenView:(UIView *)firstView secondView:(UIView *)secondView { VerticalSeparatorView *separator = [[VerticalSeparatorView alloc] init]; [firstView.superview addSubview:separator]; separator.firstView = firstView; separator.secondView = secondView; [NSLayoutConstraint activateConstraints:@[ [separator.widthAnchor constraintEqualToConstant:kTotalWidth], [separator.superview.leadingAnchor constraintEqualToAnchor:separator.leadingAnchor], [separator.superview.trailingAnchor constraintEqualToAnchor:separator.trailingAnchor], [firstView.rightAnchor constraintEqualToAnchor:separator.leftAnchor constant:kMargin], [secondView.leftAnchor constraintEqualToAnchor:separator.rightAnchor constant:-kMargin], ]]; separator.leftConstraint = [separator.leftAnchor constraintEqualToAnchor:separator.superview.leftAnchor constant:0]; // it doesn't matter what the constant is, because it hasn't been enabled return separator; } - (instancetype)init { self = [super init]; if (self) { self.translatesAutoresizingMaskIntoConstraints = false; self.userInteractionEnabled = true; self.backgroundColor = [UIColor redColor]; } return self; } #pragma mark - Handle Touches // When it first receives touches, save (a) where the view currently is; and (b) where the touch started - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.oldX = self.frame.origin.x; self.firstTouch = [[touches anyObject] locationInView:self.superview]; self.leftConstraint.constant = self.oldX; self.leftConstraint.active = true; } // When user drags finger, figure out what the new top constraint should be - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; // for more responsive UX, use predicted touches, if possible if ([UIEvent instancesRespondToSelector:@selector(predictedTouchesForTouch:)]) { UITouch *predictedTouch = [[event predictedTouchesForTouch:touch] lastObject]; if (predictedTouch) { [self updateTopConstraintOnBasisOfTouch:predictedTouch]; return; } } // if no predicted touch found, just use the touch provided [self updateTopConstraintOnBasisOfTouch:touch]; } // When touches are done, reset constraint on the basis of the final touch, // (backing out any adjustment previously done with predicted touches, if any). - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateTopConstraintOnBasisOfTouch:[touches anyObject]]; } /** Update top constraint of the separator view on the basis of a touch. This updates the top constraint of the horizontal separator (which moves the visible separator). Please note that this uses properties populated in touchesBegan, notably the `oldY` (where the separator was before the touches began) and `firstTouch` (where these touches began). @param touch The touch that dictates to where the separator should be moved. */ - (void)updateTopConstraintOnBasisOfTouch:(UITouch *)touch { // calculate where separator should be moved to CGFloat x = self.oldX + [touch locationInView:self.superview].y - self.firstTouch.y; // make sure the views above and below are not too small x = MAX(x, self.firstView.frame.origin.x + kMinWidth - kMargin); x = MIN(x, self.secondView.frame.origin.x + self.secondView.frame.size.width - (kMargin + kMinWidth)); // set constraint self.leftConstraint.constant = x; } #pragma mark - Drawing - (void)drawRect:(CGRect)rect { CGRect separatorRect = CGRectMake(kMargin, 0, kVisibleWidth, self.bounds.size.height); UIBezierPath *path = [UIBezierPath bezierPathWithRect:separatorRect]; [[UIColor blackColor] set]; [path stroke]; [path fill]; } @end 

我连接contentView右锚到分隔符左锚点和contentView左锚点分隔符右锚点,但没有任何显示后,我运行此代码。 我究竟做错了什么?

几点意见:

  1. for循环中写入的水平分隔符的约束在处理垂直分隔符时都是向后的。 你必须用前导/尾随replace所有出现的顶/底锚,反之亦然。 您已经在VerticalSeparatorClass中完成了这项工作(主要是),而不是在您创build内容视图的位置。

     UIView *previousContentView = nil; for (NSInteger i = 0; i < 4; i++) { UIView *contentView = [self addRandomColoredView]; [self.view.topAnchor constraintEqualToAnchor:contentView.topAnchor].active = true; [self.view.bottomAnchor constraintEqualToAnchor:contentView.bottomAnchor].active = true; if (previousContentView) { [VerticalSeparatorView addSeparatorBetweenView:previousContentView secondView:contentView]; NSLayoutConstraint *width = [contentView.widthAnchor constraintEqualToAnchor:previousContentView.widthAnchor]; width.priority = 250; width.active = true; } else { [self.view.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor].active = true; } previousContentView = contentView; } [self.view.trailingAnchor constraintEqualToAnchor:previousContentView.trailingAnchor].active = true; 
  2. 此外,我不清楚为什么你addSeparatorBetweenView实例方法而不是像以前一样的类方法,因为现在你正在处理两个单独的实例。 这不是问题,但效率不高。

    此外,我认为应该在顶部/底部和前/后之间翻转的一些限制滑过。 你要:

     + (instancetype)addSeparatorBetweenView:(UIView *)firstView secondView:(UIView *)secondView { VerticalSeparatorView *separator = [[VerticalSeparatorView alloc] init]; [firstView.superview addSubview:separator]; separator.firstView = firstView; separator.secondView = secondView; [NSLayoutConstraint activateConstraints:@[ [separator.widthAnchor constraintEqualToConstant:kTotalWidth], [separator.superview.topAnchor constraintEqualToAnchor:separator.topAnchor], [separator.superview.bottomAnchor constraintEqualToAnchor:separator.bottomAnchor], [firstView.rightAnchor constraintEqualToAnchor:separator.leftAnchor constant:kMargin], [secondView.leftAnchor constraintEqualToAnchor:separator.rightAnchor constant:-kMargin], ]]; separator.leftConstraint = [separator.leftAnchor constraintEqualToAnchor:separator.superview.leftAnchor constant:0]; // it doesn't matter what the constant is, because it hasn't been enabled return separator; } 
  3. 在触摸处理代码中,您仍然引用y ,而您现在要引用x

     - (void)updateTopConstraintOnBasisOfTouch:(UITouch *)touch { // calculate where separator should be moved to CGFloat x = self.oldX + [touch locationInView:self.superview].x - self.firstTouch.x; // make sure the views above and below are not too small x = MAX(x, self.firstView.frame.origin.x + kMinWidth - kMargin); x = MIN(x, self.secondView.frame.origin.x + self.secondView.frame.size.width - (kMargin + kMinWidth)); // set constraint self.leftConstraint.constant = x; }