Relativelayout или LinearLayout в разработке ios iphone?
Я хочу добавить подвью в верхней части моего представления, мне нужно пересчитать значение начала y для всех других видов и переставить их, чтобы оставить место для нового добавленного вида.
Это очень скучно, поскольку я знаю, что андроид имеет relativelayout или linearlayout может помочь автоматически сделать это.
Как легко решить эту проблему при разработке ios?
Ответы
Ответ 1
Я создал библиотеку для решения этой проблемы: CSLinearLayoutView
Вы используете его следующим образом:
// create the linear layout view
CSLinearLayoutView *linearLayoutView = [[[CSLinearLayoutView alloc] initWithFrame:self.view.bounds] autorelease];
linearLayoutView.orientation = CSLinearLayoutViewOrientationVertical;
[self.view addSubview:linearLayoutView];
// create a layout item for the view you want to display and add it to the layout view
CSLinearLayoutItem *item = [CSLinearLayoutItem layoutItemForView:someView];
item.padding = CSLinearLayoutMakePadding(5.0, 10.0, 5.0, 10.0);
item.horizontalAlignment = CSLinearLayoutItemHorizontalAlignmentCenter;
item.fillMode = CSLinearLayoutItemFillModeNormal;
[linearLayoutView addItem:item];
// add more items
Ответ 2
Я пытаюсь сделать относительный (линейный) макет некоторое время и, наконец, решил просто подклассифицировать UIScrollView, чтобы сделать это.
Я начал просто заменять layoutSubviews простой петлей через subviews, что reset истоки, сохраняя при этом запуск Y. Но некоторые неожиданные вещи добавляются в scrollview, включая представления UIInlineAutoCorrect из текстовых полей/представлений, что означает, что эти вещи были искалечены макетом. Поэтому я добавил немного логики, которая использует свойство тега UIView, чтобы определить, следует ли его выложить:
-(void) layoutSubviews{
CGFloat runningY = 0.0f;
CGFloat widestWidth = 0.0f;
for (UIView *view in self.subviews) {
if (view.tag != 1999) {
continue;
}
view.origin = CGPointMake(view.origin.x, runningY);
runningY += view.height;
if ([view autoresizingMask] == UIViewAutoresizingFlexibleWidth) {
view.width = self.width;
}
if (view.width > widestWidth) {
widestWidth = view.width;
}
}
[self setContentSize:CGSizeMake(widestWidth, runningY)];
}
Если вы по-прежнему хотите использовать уникальные теги для своих представлений, вы должны просто указать диапазон тегов, которые будут включены в макет вместо одного значения.
Ответ 3
Это не так много для подкласса UIView
, чтобы иметь смысл таких методов, как -(void)addView:toRightOfView:
и т.д. Вы можете сделать это, когда идете, портируя только те методы, которые вам нужны. Затем вы можете называть их в своем переопределении layoutSubviews
, как указывает Бенджамин.
Представления могут быть созданы с использованием IB или они могут быть написаны программно; Android отлично подходит для создания читаемых макетов, и вы можете принести эту пользу для iOS-представлений, созданных программно. То, что есть несколько устройств iOS, означает сверх читаемость, нет (пока?) Много практических преимуществ для этого шаблона.
NB. Файл "XIB" является XML файлом. Откройте его в своем любимом текстовом редакторе и посмотрите.
** ИЗМЕНИТЬ.
Вот быстрый пример, который я выбил. Он не был протестирован, но что-то вроде этого будет работать в вашем подклассе UIView
(возможно, назовите его UIRelativeView
).
- (void) addSubview:(UIView *) viewOne
toRightOfSubview:(UIView *) viewTwo
{
if (viewTwo == nil ||
[self.subviews contains:viewTwo] == NO)
{
[self addSubview:viewOne];
}
else
{
CGRect frameTwo = viewTwo.frame;
CGPoint originOne = CGPointMake(frameTwo.origin.x + frameTwo.size.width,
frameTwo.origin.y);
CGRect frameOne = CGRectZero;
frameOne.origin = originOne;
frameOne.size = viewOne.frame.size;
[viewOne setFrame:frameOne];
[self addSubview:viewOne];
}
}
- (void) moveSubview:(UIView *) viewOne
toRightOfSubview:(UIView *) viewTwo
{
if (viewTwo == nil ||
[self.subviews contains:viewTwo] == NO)
{
[self addSubview:viewOne];
}
else if ([self.subviews contains:viewOne] == NO)
{
[self addSubview:viewOne toRightOfSubview:viewTwo];
}
else
{
CGRect frameTwo = viewTwo.frame;
CGPoint originOne = CGPointMake(frameTwo.origin.x + frameTwo.size.width,
frameTwo.origin.y);
CGRect frameOne = CGRectZero;
frameOne.origin = originOne;
frameOne.size = viewOne.frame.size;
[viewOne setFrame:frameOne];
}
}
Ответ 4
Вам не повезло. iOS не имеет положений для позиционирования просмотров в разных макетах, таких как Android. Чтобы создать новый вид, вам нужно переместить все остальные подпункты.
Существуют некоторые методы изменения размера, такие как sizeToFit
и autoResizingMask
, но они не помогут вам в вашем случае здесь.
Ответ 5
iOS гораздо более ориентирована на точность пикселей, чем у Android, и использует относительные макеты, поскольку имеет дело с несколькими размерами экрана. Тем не менее, в iOS интерфейс Builder является невероятно хорошим инструментом, включенным в XCode, который вы можете использовать.
Кроме того, если вы просто добавляете subviews повторяющимся образом, вы можете переопределить метод layoutSubviews
и использовать его для ручного труда для вас. Вы говорите, что нужно "пересчитать значение начала y для всех других видов и переставить их, чтобы оставить место для нового добавленного вида"... Вы можете записать это в свой layoutSubviews
, чтобы вам не пришлось это делать каждый раз.
К сожалению, SDK по умолчанию не имеет такого значения. autoresizingMask
велики, но вы не можете использовать их для начальной компоновки; это для автоматического действительно при вращении только.
Ответ 6
Как и в iOS 9, вы можете использовать UIStackView
, который очень похож на LinearLayout
: вы добавляете представления и представление стека упорядочивает их по мере необходимости на основе ваших настроек размера:
-
Заполнение оставит три из них их натурального размера и сделает четвертое занятие самым большим пространством. Он использует приоритет обхода содержимого Auto Layout, чтобы решить, какой из них растянуть.
-
Заполните равномерно, чтобы каждый subview имел одинаковый размер, чтобы заполнить все пространство, доступное для представления стека.
-
Fill Пропорционально использует собственный размер содержимого каждого поднабора для изменения их размера на равную сумму. Таким образом, просмотр 1 был спроектирован так, чтобы иметь вдвое большую высоту, чем виды 2, 3 и 4, это соотношение останется, когда оно будет изменено - все подзоны будут пропорционально больше или меньше.
-
Equal Spacing не изменяет размеры подзонов и вместо этого изменяет интервал между подзонами, чтобы заполнить пробел.
-
Равное центрирование является самым сложным, но для многих людей также наиболее эстетично. Он пытается обеспечить, чтобы центры каждого подсмотра находились на равном расстоянии.
Вы также можете установить интервал между представлениями в представлении стека, добавив некоторые дополнения.
ПРЕДУПРЕЖДЕНИЕ. При добавлении представлений дочерних элементов стека в коде вы всегда должны использовать addArrangedSubview()
следующим образом:
stackView.addArrangedSubview(someView)
Если вы попытаетесь использовать простой старый addSubview()
, он не будет работать правильно, потому что представление стека не будет знать, чтобы его организовать.
Как для удаления, вам нужно быть осторожным, чтобы использовать stackView.removeArrangedSubview(someView)
и someView.removeFromSuperview()
, иначе представление не будет удалено правильно.
Вы можете найти полезный учебник UIStackView.