Рамка, границы и центр UIView
Я хотел бы знать, как правильно использовать эти свойства.
как я понимаю, frame
может использоваться из контейнера представления, которое я создаю.
Он задает положение представления относительно представления контейнера. Он также устанавливает размер этого представления.
и center
можно использовать из контейнера представления, которое я создаю. Это свойство изменяет положение представления относительно его контейнера.
наконец, bounds
относительно представления себя. Он изменяет область рисования для вида.
можете ли вы дать больше информации о взаимоотношениях между frame
и bounds
? Как насчет clipsToBounds
и masksToBounds
свойства?
7 ответов
поскольку вопрос, который я задал, был замечен много раз, я дам подробный ответ на него. Не стесняйтесь изменять его, если вы хотите добавить более правильный контент.
сначала резюме по вопросу: фрейм, границы и центр и их отношения.
рама вида frame
(CGRect
) - это положение его прямоугольника в superview
система координат. По умолчанию он начинается в левом верхнем углу.
границы A вид bounds
(CGRect
) выражает прямоугольник вида в собственной системе координат.
центр A center
это CGPoint
выражается в терминах superview
'ю систему координат и определяет положение точной точки зрения.
принято от UIView + позиция это отношения (они не работают в коде, поскольку они являются неформальными уравнениями) среди предыдущих свойства:
frame.origin = center - (bounds.size / 2.0)
center = frame.origin + (bounds.size / 2.0)
frame.size = bounds.size
Примечание: эти отношения не распространяется, если вид повернут. Для получения дополнительной информации, я предлагаю вам взглянуть на следующее Изображение взято из На Кухне на основе Стэнфорда 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
subview как вставка первого. Рисунок подпанель требуется знать 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
' s 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
' s положение в его 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)
значение да подпанелей, обрезается до границ из приемника. Если установлено значение NO, подвиды, фреймы которых выходят за рамки видимые границы приемника не обрезаются. Значение по умолчанию НЕТ.
другими словами, если вид frame
is (0, 0, 100, 100)
и его подвидом является (90, 90, 30, 30)
, вы увидите только часть этого подвида. Этот последнее не будет превышать границ родительского представления.
masksToBounds
эквивалентно clipsToBounds
. Вместо UIView
это свойство применяется к CALayer
. Под капотом, clipsToBounds
звонки masksToBounds
. Для дальнейших ссылок взгляните на как связь между clipsToBounds наследник UIView и masksToBounds CALayer это?.
этот вопрос уже есть хороший ответ, но я хочу дополнить его еще несколько фотографий. мой полный ответ здесь.
, чтобы помочь мне вспомнить рама, Я думаю о рама для картины на стене. Так же, как изображение может быть перемещено в любом месте на стене, система координат кадра вида является супервизором. (wall=superview, frame=view)
, чтобы помочь мне вспомнить границы, Я думаю о границы баскетбольной площадки. Баскетбол находится где-то внутри площадки, так же как система координат границ вида находится внутри самого вида. (корт=вид, баскетбол / игроки=содержимое внутри вида)
как рама, вид.центр также находится в координатах superview.
Frame vs Bounds-Пример 1
желтый прямоугольник представляет рамку вида. Зеленый прямоугольник представляет границы вида. Красная точка в обоих изображениях представлено начало кадра или границы в пределах их систем координат.
Frame
origin = (0, 0)
width = 80
height = 130
Bounds
origin = (0, 0)
width = 80
height = 130
Пример 2
Frame
origin = (40, 60) // That is, x=40 and y=60
width = 80
height = 130
Bounds
origin = (0, 0)
width = 80
height = 130
Пример 3
Frame
origin = (20, 52) // These are just rough estimates.
width = 118
height = 187
Bounds
origin = (0, 0)
width = 80
height = 130
Пример 4
это то же самое, что и Пример 2, за исключением того, что на этот раз все содержимое представления показано так, как оно выглядело бы, если бы оно не было обрезано до границ вид.
Frame
origin = (40, 60)
width = 80
height = 130
Bounds
origin = (0, 0)
width = 80
height = 130
Пример 5
Frame
origin = (40, 60)
width = 80
height = 130
Bounds
origin = (280, 70)
width = 80
height = 130
еще раз, смотрите здесь для моего ответа с более подробной информацией.
Я нашел это изображение наиболее полезным для понимания рамки, границы и т. д.
Также обратите внимание, что frame.size != bounds.size
при повороте изображения.
- свойство frame содержит прямоугольник frame, который задает размер и расположение представления в системе координат супервизора.
- свойство bounds содержит прямоугольник bounds, который задает размер представления (и его источник содержимого) в собственной локальной системе координат представления.
- свойство center содержит известную центральную точку представления в системе координат супервизора.
Я думаю, если вы думаете, что это с точки зрения CALayer
, все более ясно.
Frame на самом деле не является отдельным свойством представления или слоя вообще, это виртуальное свойство, вычисленное из границ, позиции (UIView
центр) и преобразование.
Итак, в основном, как макеты слоя / представления действительно решаются этими тремя свойствами (и точкой привязки), и любое из этих трех свойств не изменит никакого другого свойства, например изменение преобразования не меняет границ.
есть очень хорошие ответы с подробным объяснением этого поста. Я просто хотел бы сослаться на то, что есть еще одно объяснение с визуальным представлением значения фрейма, границ, Центра, преобразования, происхождения границ в WWDC 2011 video Понимание Рендеринга UIKit начиная с @4:22 до 20:10
после прочтения вышеуказанных ответов, здесь добавив мои интерпретации.
предположим, просмотр в интернете,браузер ваш frame
, который решает, где и как большой, чтобы показать веб-страницы. скроллер браузер-это ваш bounds.origin
это решает, какая часть веб-страницы будет показана. bounds.origin
- это трудно понять. Лучший способ узнать-создать приложение с одним представлением, попытаться изменить эти параметры и посмотреть, как изменяются подвиды.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 200.0f, 200.0f, 400.0f)];
[view1 setBackgroundColor:[UIColor redColor]];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];
[view2 setBackgroundColor:[UIColor yellowColor]];
[view1 addSubview:view2];
[[self view] addSubview:view1];
NSLog(@"Old view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"Old view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));
// Modify this part.
CGRect bounds = view1.bounds;
bounds.origin.x += 10.0f;
bounds.origin.y += 10.0f;
// incase you need width, height
//bounds.size.height += 20.0f;
//bounds.size.width += 20.0f;
view1.bounds = bounds;
NSLog(@"New view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"New view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));