Как рассчитать высоту UIViewController перед добавлением представления в дерево представлений?

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

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

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

Задний план:

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

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

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

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

[ThirPartyFormSheetController presentController:contentVC withSize:contentBounds];

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

Вы пробовали sizeToFit? Это метод на UIView, который изменит размер метки до желаемого размера. Вы можете получить результат из свойства frame после его вызова. Не уверен, что вы можете вызвать его в корневом представлении VC, но оно должно работать в представлении ярлыка.

LGP 08.04.2019 15:36

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

Andrei Herford 08.04.2019 15:40

@AndreiHerford - элемент управления «стороннего» не работает с автоматическим макетом? Если это так, вы хотите получить высоту загруженного представления ContentViewController на основе «целевой ширины», которую вы определяете самостоятельно? Правильно ли настроены ограничения автоматического макета в ContentViewController?

DonMag 08.04.2019 16:55

@AndreiHerford - какой элемент управления «Сторонний бланк» вы используете?

DonMag 08.04.2019 17:55

Я использую MZFormSheetController, и, насколько мне известно, он поддерживает только формы фиксированного размера. Однако это только один вариант использования, когда мне нужно программно вычислить высоту макета для заданной ширины. Было бы здорово решить проблему с формами, но общее решение было бы идеальным.

Andrei Herford 09.04.2019 07:48

Примечание: у ViewController'ов нет ни высоты, ни размеров, поскольку они являются просто классом, управляющим представлениями. Если у вас есть VC, вы обычно добавляете к нему представления, и эти представления имеют фреймы (высоту и т. д.), обычно основной UIView, прикрепленный к VC, находится с помощью VC.view

Albert Renshaw 09.04.2019 11:41

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

DonMag 09.04.2019 14:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
729
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

Спасибо, но речь идет не об измерении метки (это был только пример), а о полном размере ВК.

Andrei Herford 08.04.2019 15:53
Ответ принят как подходящий

Учитывая ширину, вы можете использовать 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 в качестве подпредставления - см. комментарии в коде):

и с дополнительным текстом, чтобы показать автоматический расчет высоты:

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

Другие вопросы по теме