ios - horizontal - UIStackView berechnet UIImageView-Höhe falsch




uistackview programmatically swift 4 (2)

Wir haben es herausgefunden! Wie in den Dokumenten angegeben, verwendet UIStackView die intrinsicContentSize seiner arrangedSubviews , um seine Höhe zu berechnen.

UIImageView meldet seine intrinsicContentSize als die gesamte Größe des Bildes (wie zu erwarten). UIStackView ignorierte meine Höhenbeschränkung und verwendete nur die intrinsicContentSize der UIStackView .

Um dies zu beheben, habe ich eine UIImageView Unterklasse erstellt, die es einem Aufrufer ermöglicht, intrinsicContentSize zu setzen. Dieser Code kann hier gefunden werden .

Dann UICollectionViewCell ich in meiner UICollectionViewCell die UIImageView-Unterklasse ' intrinsicContentSize ', sobald der Layout-Durchlauf abgeschlossen ist:

- (void)layoutSubviews {
    [super layoutSubviews];

    // Constrain the image view's content size to match the stackview's width.
    self.imageView.constrainedSize = CGSizeMake(self.stackView.frame.size.width, self.stackView.frame.size.width);

    [super layoutSubviews];

}

Ich habe ein UIStackView das in einer UIStackView enthalten ist, um einen Beitrag in einem sozialen Netzwerk UICollectionViewCell (ähnlich wie Instagram-Zellen). UIStackView enthält eine Autorenkopfzeile (benutzerdefinierte UIView ), eine UIImageView für das Inhaltsbild, eine UILabel für den Post-Body und eine UIToolbar für die Aktionen. Die endgültige Ansicht sieht so aus .

Die Höhe der UICollectionViewCell wird wie folgt festgelegt, indem Sie eine Größenzelle einrichten:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
      NTVFeedBlogCollectionViewCell *cell = [[NTVFeedBlogCollectionViewCell alloc] initWithFrame:CGRectMake(10.0f, 0.0f, collectionView.frame.size.width - 20.0f, 900000.0)];

      // ...
      // Configure the cell
      // ...

      [cell setNeedsLayout];
      [cell layoutIfNeeded];
      CGSize size = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

      return CGSizeMake(CGRectGetWidth(collectionView.frame) - 20.0f, size.height);

}

Das Problem besteht darin, dass die UIImageView die Größe der UICollectionViewCell zu erhöhen scheint, ohne die Größe der Bildansicht zu erhöhen. Dies ist das Ergebnis, wenn ich der Bildansicht ein großes Bild hinzufüge. Das gewünschte Ergebnis ist, dass das Bild ein Seitenverhältnis von 1: 1 beibehält, das auf die Breite des UIStackView beschränkt ist.

Die Größe der Lücke zwischen dem Body-Label und dem Rest des Inhalts ändert sich je nachdem, welches Bild ich verwende. Dies führt mich zu der Annahme, dass UIStackView irgendwie die Bildgröße für die Dimensionierung der Zelle berücksichtigt, da die UIStackView visuell die richtige Größe hat. Wie Sie im ersten Bild gesehen haben, ist die Zelle perfekt ausgerichtet, wenn das Bildbild der Bildansicht nicht eingestellt wurde.

Hier ist der Setup-Code für die Stapelansicht, Bildansicht und Beschriftungen:

self.stackView = [[UIStackView alloc] initWithFrame:CGRectZero];
self.stackView.translatesAutoresizingMaskIntoConstraints = NO;
self.stackView.axis = UILayoutConstraintAxisVertical;
self.stackView.distribution = UIStackViewDistributionFill;
self.stackView.alignment = UIStackViewAlignmentFill;
self.stackView.spacing = 10.0f;
self.stackView.layoutMargins = UIEdgeInsetsMake(10.0f, 10.0f, 0.0f, 10.0f);
self.stackView.layoutMarginsRelativeArrangement = YES;

[self addSubview:self.stackView];

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[stackView]-0-|"
                                                             options:0
                                                             metrics:nil
                                                               views:@{@"stackView": self.stackView}]];

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[stackView]-0-|"
                                                             options:0
                                                             metrics:nil
                                                               views:@{@"stackView": self.stackView}]];

self.imageView = [[UIImageView alloc] initWithFrame:CGRectZero];

[self.imageView setImage:[UIImage imageNamed:@"sample_image.png"]];

self.imageView.translatesAutoresizingMaskIntoConstraints = NO;
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.clipsToBounds = YES;
self.imageView.layer.masksToBounds = YES;
self.imageView.backgroundColor = [UIColor greenColor];

[self.imageView setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
[self.imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical];

[self.stackView addArrangedSubview:self.imageView];

[self.stackView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView
                                                           attribute:NSLayoutAttributeHeight
                                                           relatedBy:NSLayoutRelationEqual
                                                              toItem:self.stackView
                                                           attribute:NSLayoutAttributeWidth
                                                          multiplier:1.0f
                                                            constant:0.0f]];

self.bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.bodyLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
[self.bodyLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical];
self.bodyLabel.font = [UIFont ntv_lightFontWithSize:17.0f];
self.bodyLabel.textColor = [UIColor whiteColor];
self.bodyLabel.numberOfLines = 0;

self.bodyLabel.text = @"While the stack view allows you to layout its contents without using Auto Layout directly, you still need to use Auto Layout to position the stack view, itself.";
[self.stackView addArrangedSubview:self.bodyLabel];

self.accessoryView = [[NTVAccessoryView alloc] initWithFrame:CGRectZero];
self.accessoryView.viewModel = [NTVAccessoryManagerViewModel_Stubbed new];

[self.stackView addArrangedSubview:self.accessoryView];

Irgendwelche Ideen?


Die andere Lösung besteht darin, 2 UIStackViews vertikal zu verwenden, wenn Sie dies nicht programmgesteuert durchführen möchten. Das oberste UIStackView, das UIImageView enthält, setzt seine Höhenbeschränkung auf etwa 70% der Höhe der Superview und lässt das untere UIStackView direkt neben dem obersten stehen, so dass die verbleibenden 30% der Höhe benötigt werden.

Auf diese Weise, egal wie groß Ihr Bild ist, wird es immer 70% der Höhe einnehmen.





uistackview