Как определить маржу сгруппированного UITableView (или лучше, как его установить)?
Сгруппированный UITableView помещает маркер между краем представления и ячейками таблицы. Раздражающе (для меня) этот запас является некоторой функцией ширины представления.
В моем приложении у меня есть два UITableView с разной шириной, которые я ищу, чтобы выровнять края ячеек.
Можно ли получить этот запас? Или лучше установить этот запас?
веселит,
--Ben
Ответы
Ответ 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));
}
Ответ 7
Теперь это доступно через свойство UITableViewCell:
@property(nonatomic) UIEdgeInsets separatorInset
Apple Docs - UITableViewCell - seperatorInset
Ответ 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.
Надеюсь, что это поможет...