Где определить размер UIView - PullRequest
28 голосов
/ 09 июля 2009

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

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

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

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

Когда запрашивается представление UIViewController и свойство view равно 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 (и, таким образом, присвоить ему свойство frame)? Или я что-то упустил и есть ли другие возможности?

Ответы [ 3 ]

8 голосов
/ 09 июля 2009

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

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

0 голосов
/ 20 марта 2013

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

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

0 голосов
/ 23 декабря 2009

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: только что нашел это примечание в документации UIViewController: Примечание. Не следует использовать контроллеры представлений для управления представлениями, которые заполняют только часть их окна, то есть только часть области, определяемой прямоугольником содержимого приложения. Если вы хотите, чтобы интерфейс состоял из нескольких меньших представлений, вставьте их все в одно корневое представление и управляйте этим представлением с помощью контроллера представлений.

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

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

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