Подтвердить что ты не робот

Где определить размер UIView

Резюме. Как должен UIViewController знать размер своего экземпляра UIView при инициализации этого представления?

Специальный метод инициализации для UIView - это метод initWithFrame:(CGRect)frame. Это устанавливает кадр для вновь созданного UIView. Этот метод можно вызвать из метода load t UIViewController's, если запрошено представление контроллера вида. Документация UIViewController указывает на размер подкласса и вида:

При создании представлений для вашего вида иерархии, вы всегда должны устанавливать авторезистирование свойств ваших представлений. Когда контроллер просмотра отображается на экран, его корневой вид обычно измененный в соответствии с доступным пространством, которые могут варьироваться в зависимости от текущую ориентацию окна и наличие других элементов интерфейса например, в строке состояния.

Итак, экземпляр UIViewController должен установить эти свойства. Пока что так хорошо, UIViewController пока не должен знать, насколько велика его точка зрения или будет.

Когда запрашивается представление UIViewController и свойство представления равно nil, вызывается метод loadView контроллера вида. Теперь есть проблема, потому что UIView необходимо инициализировать, но контроллер представления все еще не знает, какой размер должен быть вид. Насколько велика вы должны инициализировать это представление? Где в коде вы определяете размер представления?

Вы можете инициализировать представление нулевым прямоугольником (CGRectZero):

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}

И позвольте вызывающему устройству установить рамку представления следующим образом:

UIViewController *viewController = [[MyUIViewController alloc] init];
// next two lines are normally combined, but for clarity they are not now
UIView *view = viewController.view;
view.frame = CGRectMake(0, 0, 200, 200);

Это запрашивает представление из контроллера представления (viewController.view) и, таким образом, загружает его представление с помощью метода loadView. Этот метод loadView инициализирует представление с помощью CGRectZero. Затем вызывающий абонент устанавливает свой кадр (view.frame =...)

Дело в том, что свойство frame на представлении задано дважды, что может привести к еще большему удвоению работы, если ваш пользовательский UIView выполняет некоторые расширенные макеты в методе setFrame (например, размещение и изменение размеров подвью). Это можно предотвратить, создав специальный метод инициализации для UIViewController, который уже запрашивает вызывающего абонента для CGRect, который вы храните в ivar. В то время, когда вызывается метод loadView, вы используете этот ivar для создания представления.

Каков хороший способ пойти сюда? Или дважды установите два кадра (инициализируя с помощью CGRectZero и устанавливая впоследствии), или предоставляя UIViewController новый метод инициализации с помощью CGRect (и тем самым предоставляя ему свойство кадра)? Или я что-то упускаю и есть другие возможности?

4b9b3361

Ответ 1

Вам не нужно использовать назначенный инициализатор. Просто используйте init, как в [[UIView alloc] init]. Назначенный инициализатор должен использоваться из инициализаторов подклассов.

С другой стороны, установка кадра дважды не должна навредить. Выполнение множества задач в setFrame: необычно. Макет обычно выполняется в layoutSubviews и выполняется только один раз.

Ответ 2

В настоящее время я пытаюсь выполнить то же самое после подкласса из UIViewController, чтобы создать общий компонент, и заметил, что что-то довольно странное:

UIViewController имеет метод loadView, который вы можете переопределить (цитируя документацию). "Здесь подклассы должны создавать свою собственную иерархию представлений".

Итак, я создаю свою иерархию представлений, компонуя свой экран с использованием размера фрейма по умолчанию (поскольку я, возможно, не знаю фрейма, я должен отображать вещи во время вызова loadView).

Но тогда, по какому звонку я правильно устанавливаю размеры кадра? Aka: в какой момент мой диспетчер представления узнает об этом, посмотрите реальный размер?

Должен ли я создать "setFrame" в моем подклассе ViewController, который должен вызвать объект, создающий диспетчер представлений? что кажется странным.

drvdijk: у вас есть решение вашей проблемы?

EDIT: только что нашел эту записку в документации UIViewController: Примечание. Вы не должны использовать контроллеры представлений для управления представлениями, которые заполняют только часть их окна, то есть только часть области, определяемой прямоугольником содержимого приложения. Если вы хотите иметь интерфейс, состоящий из нескольких меньших видов, вставьте их все в одно корневое представление и управляйте этим представлением с помощью вашего контроллера вида.

Итак, кажется, что основной вид UIViewController всегда полноэкранный. Период.

Это создает для меня проблему, поскольку я пытаюсь создать пользовательский UITabBarViewController (чтобы иметь возможность отображать пользовательские изображения на вкладке, а не синий градиент): мой tabBarViewController должен отображать subviewcontrollers в часть только окно...

Ответ 3

Вы можете рассчитать границы доступного пространства экрана (что зависит от наличия других видов, таких как панель навигации, панель вкладок и строка состояния). Эти ограничения можно использовать для параметра frame в [[UIView alloc] initWithFrame:] в loadView.

Если это то, что вы хотите, тогда вы можете найти мой ответ здесь: Определите правильный размер в loadView