Relativelayout или LinearLayout в разработке ios для iphone? - PullRequest
10 голосов
/ 16 августа 2011

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

Этоэто очень скучно, так как я знаю, что Android имеет относительное или линейное расположение, которое может помочь автоматически сделать это.

Как легко решить эту проблему в ios development?

Ответы [ 6 ]

17 голосов
/ 04 мая 2012

Я создал библиотеку для решения именно этой проблемы: 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
4 голосов
/ 20 декабря 2011

Я некоторое время пытался сделать относительный (линейный) макет и, наконец, решил просто создать подкласс UIScrollView, чтобы сделать это.

Я начал просто заменять layoutSubviews простым циклом, проходящим по подпредставлениям.которые сбрасывают источники при сохранении работающего Y. Но некоторые непредвиденные вещи добавляются в представление прокрутки, включая представления UIInlineAutoCorrect из textfields / views, что означает, что эти вещи были искажены макетом.Поэтому я добавил немного логики, которая использует свойство тега 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 голосов
/ 24 августа 2011

Подкласс UIView не так уж важен для понимания таких методов, как -(void)addView:toRightOfView: и т. Д. Вы можете делать это по ходу, портируя только те методы, которые вам нужны.Затем вы можете вызвать их в переопределении layoutSubviews, как указывает Бенджамин.

Представления могут быть построены с использованием IB, или они могут быть написаны программно;Android хорошо зарекомендовал себя в создании удобочитаемых макетов, и вы можете использовать это преимущество для представлений iOS, созданных программным способом.То, что iOS-устройств немного, означает, что помимо читабельности нет (пока?) Многих практических преимуществ для этого шаблона.

Примечание.Файл "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];
  }
}
2 голосов
/ 16 августа 2011

Тебе здесь не повезло. iOS не имеет положений для позиционирования видов в разных макетах, таких как Android .Вам нужно изменить положение всех других подпредставлений, чтобы проложить путь для нового представления.

Существуют некоторые методы изменения размера представления, такие как sizeToFit и autoResizingMask, но они не помогут вам в вашем случае здесь.

1 голос
/ 13 декабря 2015

Начиная с iOS 9, вы можете использовать UIStackView, который работает очень похоже на LinearLayout: вы добавляете представления, а представление стека упорядочивает их по мере необходимости в соответствии с вашими настройками размеров:

  • Заполнение оставит три из них их естественного размера, а четвертый займет больше места. Он использует приоритет объятия содержимого Auto Layout, чтобы решить, какой из них растянуть.

  • Заполнить Одинаково сделает каждый подпредставление одинакового размера, чтобы они заполнили все пространство, доступное для представления стека.

  • Заполнить Пропорционально использует внутренний размер контента каждого подпредставления, чтобы изменить их размер на равную величину. Таким образом, вид 1 был спроектирован так, чтобы иметь высоту, в два раза превышающую высоту видов 2, 3 и 4, это соотношение будет сохраняться при изменении их размера - все подпредставления пропорционально увеличиваются или уменьшаются.

  • Равный интервал не изменяет размер подпредставлений, а вместо этого изменяет интервал между подпредставлениями, чтобы заполнить пространство.

  • Равное центрирование является наиболее сложным, но для многих людей также наиболее эстетически приятным. Он пытается обеспечить одинаковое расстояние между центрами каждого подпредставления.

Вы также можете установить интервал между представлениями в виде стека, добавив некоторые отступы.

ПРЕДУПРЕЖДЕНИЕ : при добавлении дочерних представлений стекового представления в коде вы всегда должны использовать addArrangedSubview() следующим образом:

stackView.addArrangedSubview(someView)

Если вы попытаетесь использовать обычный старый addSubview(), он не будет работать правильно, потому что представление стека не будет знать, как это организовать.

Что касается удаления, вы должны быть осторожны при использовании stackView.removeArrangedSubview(someView) и someView.removeFromSuperview(), иначе представление не будет удалено правильно.

Может оказаться полезным мое руководство по UIStackView .

1 голос
/ 16 августа 2011

iOS гораздо больше ориентирована на точность пикселей, чем Android, которая использует относительные макеты, поскольку она имеет дело с экранами нескольких размеров. Однако в iOS Interface Builder - невероятно хороший инструмент, включенный в XCode, который вы можете использовать.

Кроме того, если вы просто добавляете подпредставления в повторяющемся порядке, вы можете переопределить метод layoutSubviews и использовать его для ручного труда. Вы упомянули о необходимости «пересчитать значение источника y для всех других представлений и переместить их, чтобы оставить место для нового добавленного представления» ... Вы можете закодировать это в свой layoutSubviews, чтобы вам не пришлось это делать себя каждый раз.

К сожалению, в SDK по умолчанию ничего из этого не включено. autoresizingMask отлично, но вы не можете использовать это для первоначального макета; на самом деле это только при автоматическом вращении.

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