Как рассчитать высоту UIViewController перед добавлением вида в дерево просмотра? - PullRequest
0 голосов
/ 08 апреля 2019

Мне нужно измерить высоту простого VC на основе автопрокладки для заданной ширины. Например, простой UIViewController только с одной меткой, которая позиционируется с использованием ограничений в начале, в конце, сверху и снизу к корневому представлению VC.VC должен не иметь фиксированный размер, но автоматически адаптироваться к содержимому метки.

Это только пример, конечно, у VC может быть другой контент, который влияет на размер.

Как я могу рассчитать размер VC для данной ширины и содержимого метки бездобавить его в иерархию представлений?

Фон:

Я использую сторонний элемент управления FormSheet, который позволяет легко отображать любой ViewController в виде листа формы с различнымистили, переходы и т. д. Единственным недостатком является то, что необходимо указать фиксированный размер листа перед представлением VC.

Хотя это прекрасно работает для VC со «статическим» содержимым /фиксированные размеры, даже этикетка с разными текстами для разных языков может нарушить дизайн.

Таким образом, я ищу что-то вроде этого:

ContentViewController *contentVC = [ContentViewController new];
CGRect contentBounds = [SomeClass calculateAutoLayoutHeightForView:contentVC.view withFixedWidth:500];

[ThirPartyFormSheetController presentController:contentVC withSize:contentBounds];

Как это можно сделать?

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Учитывая ширину, вы можете использовать systemLayoutSizeFittingSize:UILayoutFittingCompressedSize, чтобы определить, какой будет высота после того, как автонастройка выполнит свою работу.

Предполагая, что ограничения в представлении для показа установлены правильно:

CGFloat w = 500.0;
[loadedView.widthAnchor constraintEqualToConstant:w].active = YES;

// caluclate the size using FittingCompressedSize
CGSize contentBounds = [loadedView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Вот простой пример (нужно только назначить класс ViewController контроллеру представления в раскадровке ... никаких IBOutlets не требуется).Множество комментариев в коде должны прояснить все:

//
//  ViewController.h
//  Created by Don Mag on 4/8/19.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

//
//  ViewController.m
//  Created by Don Mag on 4/8/19.
//

#import "ViewController.h"
#import "FormViewController.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // add a button we'll use to show the form VC
    UIButton *b = [UIButton new];
    b.translatesAutoresizingMaskIntoConstraints = NO;
    [b setTitle:@"Show Form" forState:UIControlStateNormal];
    [b setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [b setBackgroundColor:[UIColor redColor]];

    [self.view addSubview:b];

    [NSLayoutConstraint activateConstraints:
     @[
       [b.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:20.0],
       [b.widthAnchor constraintEqualToAnchor:self.view.widthAnchor multiplier:0.75],
       [b.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor]
       ]
     ];

    [b addTarget:self action:@selector(loadAndShowForm:) forControlEvents:UIControlEventTouchUpInside];

}

- (void) loadAndShowForm:(id)sender {

    // instantiate the form view controller
    FormViewController *vc = [FormViewController new];

    // get a reference to its view
    UIView *v = vc.view;

    // use auto-layout
    v.translatesAutoresizingMaskIntoConstraints = NO;

    // set the label text in the form view
    vc.topLabel.text = @"This is a bunch of text for the TOP label in the Form VC";
    vc.bottomLabel.text = @"This is a bunch of text for the BOTTOM label in the Form VC. It's enough text to cause a few lines of word-wrap, assuming we're running on an iPhone.";

    // specify a width for the form view
    // we'll use width of current view minus 60 (30-pts on each side)
    CGFloat w = self.view.frame.size.width - 60.0;
    [v.widthAnchor constraintEqualToConstant:w].active = YES;

    // caluclate the size using FittingCompressedSize
    CGSize contentBounds = [v systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

    // because we set the width constraint, we now have the "compressed" height
    //[ThirdPartyFormSheetController presentController:contentVC withSize:contentBounds];

    // debugging from here down
    NSLog(@"Auto-layout resulting size: %@", [NSValue valueWithCGSize:contentBounds]);

    // set the height for the form view
    [v.heightAnchor constraintEqualToConstant:contentBounds.height].active = YES;

    // add it to the view, so we can confirm the height calculation
    [self.view addSubview:v];

    // center it on the view
    [NSLayoutConstraint activateConstraints:
     @[
       [v.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
       [v.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor]
       ]
     ];

}

@end

//
//  FormViewController.h
//  Created by Don Mag on 4/8/19.
//

#import <UIKit/UIKit.h>

@interface FormViewController : UIViewController

@property (strong, nonatomic) UILabel *topLabel;
@property (strong, nonatomic) UITextField *theTextField;
@property (strong, nonatomic) UILabel *bottomLabel;

@end

//
//  FormViewController.m
//  Created by Don Mag on 4/8/19.
//

#import "FormViewController.h"

@interface FormViewController ()
@end

@implementation FormViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor redColor];

    // create a multi-line "top label"
    _topLabel = [UILabel new];
    _topLabel.backgroundColor = [UIColor cyanColor];
    _topLabel.text = @"Hello Top Label";
    _topLabel.numberOfLines = 0;

    // create a text field
    _theTextField = [UITextField new];
    _theTextField.backgroundColor = [UIColor greenColor]; // just to make it easy to see
    _theTextField.borderStyle = UITextBorderStyleRoundedRect;
    _theTextField.text = @"The Text Field";

    // create a multi-line "bottom label"
    _bottomLabel = [UILabel new];
    _bottomLabel.backgroundColor = [UIColor cyanColor];
    _bottomLabel.text = @"Hello Bottom Label";
    _bottomLabel.numberOfLines = 0;

    // we're using auto-layout and constraints
    _topLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _theTextField.translatesAutoresizingMaskIntoConstraints = NO;
    _bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;

    // add to view
    [self.view addSubview:_topLabel];
    [self.view addSubview:_theTextField];
    [self.view addSubview:_bottomLabel];

    // these elements and constraints will define the height of the content
    [NSLayoutConstraint activateConstraints:
     @[

       // constrain top label leading, trailing and top to top of view, all at 20-pts
       [_topLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20.0],
       [_topLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0],
       [_topLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0],

       // constrain text field leading and trailing, and top to bottom of top label, all at 20-pts
       [_theTextField.topAnchor constraintEqualToAnchor:_topLabel.bottomAnchor constant:20.0],
       [_theTextField.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0],
       [_theTextField.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0],

       // constrain bottom label leading, trailing and top to bottom of text field, all at 20-pts
       [_bottomLabel.topAnchor constraintEqualToAnchor:_theTextField.bottomAnchor constant:20.0],
       [_bottomLabel.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-20.0],
       [_bottomLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0],

       // AND constrain bottom label to bottom of view at 20-pts
       [_bottomLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0]

       ]
     ];

}

@end

Результат (добавление представления загруженного VC в качестве подпредставления -см. комментарии в коде):

enter image description here

и с дополнительным текстом для отображения автоматического расчета высоты:

enter image description here

Если вы измените количество текста для надписей (задается в ViewController.m), вы увидите, что высота рассчитана правильно.

0 голосов
/ 08 апреля 2019

Swift: Если все, что вам нужно, это рассчитать высоту на основе текста метки, вы можете использовать это решение

https://stackoverflow.com/a/25187891/7848711

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...