Подтвердить что ты не робот

Как определить маржу сгруппированного UITableView (или лучше, как его установить)?

Сгруппированный UITableView помещает маркер между краем представления и ячейками таблицы. Раздражающе (для меня) этот запас является некоторой функцией ширины представления.

В моем приложении у меня есть два UITableView с разной шириной, которые я ищу, чтобы выровнять края ячеек.

Можно ли получить этот запас? Или лучше установить этот запас?

веселит, --Ben

4b9b3361

Ответ 1

Создав (и используя!) подкласс UITableViewCell, вы можете достичь того, что ищете. Просто переместите contentview и backgroundview вокруг в layoutsubviews, как в примере кода ниже, который сдвигает видимые части ячейки 20pt вправо.

- (void) layoutSubviews
{
    NSLog (@"Cell/contentview/backgroundview before:\n%@\n%@\n%@", self, self.contentView, self.backgroundView);
    [super layoutSubviews];
    CGRect frame = self.backgroundView.frame;
    frame.origin.x += 20;
    frame.size.width -= 20;
    self.backgroundView.frame = frame;
    frame = self.contentView.frame;
    frame.origin.x += 20;
    frame.size.width -= 20;
    self.contentView.frame = frame;

    NSLog (@"Cell/contentview/backgroundview after:\n%@\n%@\n%@", self, self.contentView, self.backgroundView);
}

Ответ 2

Сгруппированная ширина таблицы в отношении к марже ячейки

TBWidth (от 0 до 20) Левая маржа = TBWidth - 10

TBWidth (от 20 до 400) Левая маржа = 10

TBWidth (от 401 до 546) Левая маржа = 31

TBWidth (от 547 до 716) Left Margin = apx 6% tableView

TBWidth (от 717 до 1024) Левая маржа = 45

- (float) groupedCellMarginWithTableWidth:(float)tableViewWidth
{
    float marginWidth;
    if(tableViewWidth > 20)
    {
        if(tableViewWidth < 400)
        {
            marginWidth = 10;
        }
        else
        {
            marginWidth = MAX(31, MIN(45, tableViewWidth*0.06));
        }
    }
    else
    {
        marginWidth = tableViewWidth - 10;
    }
    return marginWidth;
}

Ответ 3

Я использовал реализацию Matthew Thomas, но он ненадежный (он сломан, если вы используете авторотацию в своих контроллерах) и имеет много жестко закодированного кода... Я понял, что есть очень простое решение, моя реализация - это одна строка код:

- (float)cellMargins
{
    return self.backgroundView.frame.origin.x * 2;
}

Это намного лучше ИМО:)

EDIT: моя реализация также была ненадежной (она не работает должным образом при переключении в/из режима редактирования), это моя окончательная реализация (я обрабатывал поля справа и слева отдельно):

- (float)leftMargin
{
    return self.contentView.frame.origin.x;
}

- (float)rightMargin
{
    CGRect frame = self.contentView.frame;
    float containerWidth = frame.size.width;
    float margin = self.frame.size.width - (containerWidth + frame.origin.x);
    return margin;
}

- (float)cellMargins
{
    return ([self leftMargin] + [self rightMargin]);
}

Ответ 4

Обновлен код Мэтью Томаса для расчета полей полей. Создано через категорию UITableView. Это может быть полезно, когда вам нужно определить высоту текста в ячейке, и вы не знаете ширину этой ячейки.

Итак, фактическая ячейка может быть рассчитана как

cell.width = tableView.width - tableView.cellsMargin * 2;

Здесь код

@implementation UITableView (CellsMargins)

// This is black magic
// from
// http://stackoverflow.com/questions/4708085/how-to-determine-margin-of-a-grouped-uitableview-or-better-how-to-set-it

- (CGFloat)cellsMargin {

   // No margins for plain table views
   if (self.style == UITableViewStylePlain) {
      return 0;
   }

   // iPhone always have 10 pixels margin
   if (! isIPad()) {
      return 10;
   }

   CGFloat tableWidth = self.frame.size.width;

   // Really small table
   if (tableWidth <= 20) {
      return tableWidth - 10;
   }

   // Average table size
   if (tableWidth < 400) {
      return 10;
   }

   // Big tables have complex margin logic
   // Around 6% of table width,
   // 31 <= tableWidth * 0.06 <= 45

   CGFloat marginWidth  = tableWidth * 0.06;
   marginWidth = MAX(31, MIN(45, marginWidth));
   return marginWidth;
}

@end

Ответ 5

Я хотел бы дополнить ответ Мэтью кодом с настройкой фиксированного поля.

  • Подкласс UITableViewCell.
  • Реализовать setFrame:
- (void)setFrame:(CGRect)frame
{
    CGFloat inset = 15.0;
    CGFloat tableWidth = 400.0;
    frame.origin.x -= [self groupedCellMarginWithTableWidth:tableWidth] - inset;
    frame.size.width = frame.size.width + 2 * ([self groupedCellMarginWithTableWidth:tableWidth] - inset);
    [super setFrame:frame];
}

Это позволит установить левое и правое поле на 15,0, тогда как ширина таблицы может отличаться.

Ответ 6

Более точное левое поле для "эластичной" зоны вместо "apx. 6% calc. '

Боковое примечание: iPad реализует дополнительные верхние и нижние дополнения в дополнение к заполнению левого поля, это 10.0f ниже ширины таблицы 400.0f и 31.0f в противном случае.

-(CGFloat)leftMarginForTableView:(UITableView*)tableView
{
    if (tableView.style != UITableViewStyleGrouped) return 0;
    CGFloat widthTable = tableView.bounds.size.width;
    if (isPhone)              return (10.0f);
    if (widthTable <= 400.0f) return (10.0f);
    if (widthTable <= 546.0f) return (31.0f);
    if (widthTable >= 720.0f) return (45.0f);
    return (31.0f + ceilf((widthTable - 547.0f)/13.0f));
}

Ответ 8

На всякий случай, если кому-то это понадобится, функция для левого поля заголовка раздела при получении из tableView:titleForHeaderInSection: выглядит следующим образом:

- (float)marginForSectionTitleOnGroupedTableView {
   float width = self.width;

   if (width <= 400) return 19;
   else if (width >= 401 && width < 547) return 40;
   else if (width >= 547 && width < 560) return 41;
   else if (width >= 560 && width < 573) return 42;
   else if (width >= 573 && width < 586) return 43;
   else if (width >= 586 && width < 599) return 44;
   else if (width >= 599 && width < 612) return 45;
   else if (width >= 612 && width < 625) return 46;
   else if (width >= 625 && width < 639) return 47;
   else if (width >= 639 && width < 652) return 48;
   else if (width >= 652 && width < 665) return 49;
   else if (width >= 665 && width < 678) return 50;
   else if (width >= 678 && width < 691) return 51;
   else if (width >= 691 && width < 704) return 52;
   else if (width >= 704 && width < 717) return 53;

   // if (width >= 717) 
   return 54;
}

Для ширины больше 401, по-видимому, размер поля составляет около 7,5% от ширины таблицы; но при попытке сопоставить другое представление с заголовком раздела, выравнивание не работает должным образом; поэтому вербальный подход работает лучше.

Ответ 9

Я пробовал другой подход. Но не уверен, всегда ли это работает. У меня был сгруппированный UITableView и нужно было настроить индивидуальный просмотр заголовка. Но, как вы знаете, при внедрении метода viewForHeader inSection мы не можем определить поля для нашего созданного представления. Итак, что я сделал, сначала добавьте свойство CGRect в файл ViewController.m:

@property(nonatomic)CGRect groupedCellRectangle;

и в UITableViewDelegate:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    static BOOL groupFrameInitialized = NO;
    if(!groupFrameInitialized){
        groupFrameInitialized = YES;
        self.groupedCellRectangle = cell.contentView.frame;
    }
}

после этого, в моем методе viewForHeader inSection:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
  UIView *v = [[UIView alloc] initWithFrame:CGRectMake(self.groupedCellRectangle.origin.x, 0, self.groupedCellRectangle.size.width, 28)];
  [v setBackgroundColor:[UIColor clearColor]];
  UILabel *label = [[UILabel alloc] initWithFrame:v.frame];
  label.text = @"KAF";
  [v addSubview:label];
  return v;
}

результат такой, как я предполагал. groupedCellRectangle успешно сохранил значение CGRect с маржей.

Идея такого подхода заключалась в том, что UITableView всегда вызывал метод viewForHeader после вызова CallDisplay.

Надеюсь, что это поможет...