Ответ 1
Поскольку вопрос, который я задал, был замечен много раз, я предоставлю подробный ответ. Не стесняйтесь изменять его, если вы хотите добавить более правильный контент.
Сначала перескажите вопрос: кадр, границы и центр и их отношения.
Рамка Вид frame
(CGRect
) - это положение его прямоугольника в системе координат superview
. По умолчанию он начинается в левом верхнем углу.
Границы Вид bounds
(CGRect
) выражает прямоугольник представления в своей собственной системе координат.
Центр A center
- это CGPoint
, выраженный в терминах системы координат superview
и определяет положение точной центральной точки вида.
Взято из UIView + position, это отношения (они не работают в коде, поскольку они являются неформальными уравнения) среди предыдущих свойств:
-
frame.origin = center - (bounds.size / 2.0)
-
center = frame.origin + (bounds.size / 2.0)
-
frame.size = bounds.size
ПРИМЕЧАНИЕ. Эти отношения не применяются, если виды повернуты. Для получения дополнительной информации я предложу вам взглянуть на следующее изображение, взятое из Кухонный ящик на основе курс 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
представления (см. Предыдущие уравнения).
Рассмотрение примера1 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 frame is: %@", NSStringFromCGRect([view1 frame]));
NSLog(@"view1 bounds is: %@", NSStringFromCGRect([view1 bounds]));
NSLog(@"view1 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)
Установка этого значения в значение YES приводит к тому, что subviews будут обрезаны до границ приемника. Если установлено значение NO, subviews, чьи рамки выходят за пределы видимые границы приемника не обрезаны. Значение по умолчанию НЕТ.
Другими словами, если представление frame
равно (0, 0, 100, 100)
, а его подвью (90, 90, 30, 30)
, вы увидите только часть этого поднабора. Последнее не будет превышать границы родительского вида.
masksToBounds
эквивалентен clipsToBounds
. Вместо UIView
это свойство применяется к CALayer
. Под капотом clipsToBounds
вызывается masksToBounds
. Для дальнейших ссылок взгляните на Какова связь между клипами UIViewToBounds и масками CALayerToBounds?.