Поскольку вопрос, который я задавал, встречался много раз, я приведу подробный ответ на него. Не стесняйтесь изменять его, если хотите добавить более правильный контент.
Сначала краткий обзор вопроса: рамка, границы, центр и их отношения.
Рамка Вид frame
(CGRect
) - это положение его прямоугольника в системе координат superview
. По умолчанию он начинается слева вверху.
Границы Вид bounds
(CGRect
) выражает прямоугольник вида в своей собственной системе координат.
Центр A center
- это CGPoint
, выраженное в системе координат superview
, и оно определяет положение точной центральной точки вида.
Взято из UIView + position это отношения (они не работают в коде, поскольку они являются неформальными уравнениями) среди предыдущих свойств:
ПРИМЕЧАНИЕ: Эти отношения не применяются, если представления повернуты. Для получения дополнительной информации, я предлагаю вам взглянуть на следующее изображение, взятое с Кухонный ящик на основе Stanford CS193p курс. Кредиты идут на @Rhubarb.
Использование frame
позволяет изменить положение и / или изменить размер представления в пределах superview
. Обычно может использоваться из superview
, например, при создании определенного подпредставления. Например:
// view1 will be positioned at x = 30, y = 20 starting the top left corner of [self view]
// [self view] could be the view managed by a UIViewController
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];
view1.backgroundColor = [UIColor redColor];
[[self view] addSubview:view1];
Когда вам нужны координаты для рисования внутри view
, вы обычно ссылаетесь на bounds
. Типичным примером может быть рисование внутри view
подпредставления как вставка первого. Для создания подпредставления необходимо знать bounds
суперпредставления. Например:
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 400.0f, 400.0f)];
view1.backgroundColor = [UIColor redColor];
UIView* view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];
view2.backgroundColor = [UIColor yellowColor];
[view1 addSubview:view2];
При изменении bounds
представления происходит другое поведение.
Например, если вы измените bounds
size
, frame
изменится (и наоборот). Изменение происходит вокруг center
вида. Используйте код ниже и посмотрите, что произойдет:
NSLog(@"Old Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"Old Center %@", NSStringFromCGPoint(view2.center));
CGRect frame = view2.bounds;
frame.size.height += 20.0f;
frame.size.width += 20.0f;
view2.bounds = frame;
NSLog(@"New Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"New Center %@", NSStringFromCGPoint(view2.center));
Кроме того, если вы измените bounds
origin
, вы измените origin
его внутренней системы координат. По умолчанию origin
находится на (0.0, 0.0)
(верхний левый угол). Например, если вы измените origin
на view1
, вы увидите (прокомментируйте предыдущий код, если хотите), что теперь верхний левый угол для view2
касается view1
. Мотивация довольно проста. Вы говорите view1
, что его верхний левый угол теперь находится в позиции (20.0, 20.0)
, но, поскольку view2
frame
origin
начинается с (20.0, 20.0)
, они будут совпадать.
CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame;
origin
представляет положение view
в пределах superview
, но описывает положение центра bounds
.
Наконец, bounds
и origin
не являются связанными понятиями. Оба позволяют получить frame
вида (см. Предыдущие уравнения).
Тематическое исследование View1
Вот что происходит при использовании следующего фрагмента.
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];
view1.backgroundColor = [UIColor redColor];
[[self view] addSubview:view1];
NSLog(@"view1's frame is: %@", NSStringFromCGRect([view1 frame]));
NSLog(@"view1's bounds is: %@", NSStringFromCGRect([view1 bounds]));
NSLog(@"view1's center is: %@", NSStringFromCGPoint([view1 center]));
Относительное изображение.
Это вместо того, что произойдет, если я изменю [self view]
границы следующим образом.
// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];
Относительное изображение.
Здесь вы говорите [self view]
, что его левый верхний угол теперь находится в позиции (30.0, 20.0), но поскольку начало кадра view1
начинается с (30.0, 20.0), они будут совпадать.
Дополнительные ссылки (для обновления другими ссылками, если хотите)
О clipsToBounds
(источник Apple Doc)
Установка этого значения в YES заставляет подпредставления обрезаться до границ
получателя. Если установлено значение NO, подпредставления, кадры которых выходят за рамки
видимые границы приемника не ограничены. Значением по умолчанию является
NO.
Другими словами, если frame
представления - (0, 0, 100, 100)
, а его подпредставление - (90, 90, 30, 30)
, вы увидите только часть этого подпредставления. Последнее не будет выходить за пределы родительского представления.
masksToBounds
эквивалентно clipsToBounds
. Вместо UIView
это свойство применяется к CALayer
. Под капотом clipsToBounds
звонит masksToBounds
. Для дальнейших ссылок взгляните на Какова связь между clipsToBounds UIView и masksToBounds CALayer? .