Как установить ширину ячейки в UITableView в сгруппированном стиле

107

Я работал над этим около двух дней, поэтому решил поделиться с вами своими знаниями.

Возникает вопрос: можно ли уменьшить ширину ячейки в сгруппированном UITableView?

Ответ - нет.

Но есть два способа обойти эту проблему.

Решение №1: Более тонкая таблица. Можно изменить рамку tableView, чтобы таблица была меньше. Это приведет к тому, что UITableView отобразит внутреннюю ячейку с уменьшенной шириной.

Решение для этого может выглядеть так:

-(void)viewWillAppear:(BOOL)animated
{
    CGFloat tableBorderLeft = 20;
    CGFloat tableBorderRight = 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x += tableBorderLeft; // make the table begin a few pixels right from its origin
    tableRect.size.width -= tableBorderLeft + tableBorderRight; // reduce the width of the table
    tableView.frame = tableRect;
}

Решение # 2: визуализация ячеек изображениями

Это решение описано здесь: http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html

Надеюсь, эта информация будет вам полезна. Мне потребовалось около 2 дней, чтобы попробовать множество возможностей. Вот что осталось.

Томен
источник
3
Я думаю, это должно было быть задано как вопрос только со второй строкой («Вопрос: ...»), затем Решение №1 и Решение №2 были опубликованы как два отдельных ответа, причем один из них был принят. Затем, если другие пользователи добавят свои собственные ответы, и один из них окажется лучше, принятый ответ можно будет изменить позже.
General Mike

Ответы:

226

Лучший и более чистый способ добиться этого - создать подкласс UITableViewCell и переопределить его -setFrame:метод следующим образом:

- (void)setFrame:(CGRect)frame {
    frame.origin.x += inset;
    frame.size.width -= 2 * inset;
    [super setFrame:frame];
}

Почему лучше? Потому что два других хуже.

  1. Отрегулируйте ширину представления таблицы в -viewWillAppear:

    Прежде всего, это ненадежно, контроллер супервизора или родительского представления может регулировать фрейм табличного представления дальше после -viewWillAppear:вызова. Конечно, вы можете создать подкласс и переопределить -setFrame:для своего UITableView точно так же, как я делаю здесь для UITableViewCells. Однако создание подклассов от UITableViewCells - это очень распространенный, легкий и Apple способ.

    Во-вторых, если ваш UITableView имеет backgroundView, вы не хотите, чтобы его backgroundView сужался вместе. Сохранение ширины backgroundView при уменьшении ширины UITableView - нетривиальная работа, не говоря уже о том, что расширение подпредставлений за пределы его супервизора - не очень элегантная вещь в первую очередь.

  2. Пользовательский рендеринг ячеек для имитации более узкой ширины

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

an0
источник
2
это красивое и элегантное решение, я сделал это в категории :) Также отмечу, что чем больше прозрачных объектов, тем больше загрузка процессора :)
mister koz
11
@misterkoz - предостережение: некоторые элементы управления iOS (для определенности UIDatePicker) внутренне используют UITableViewCells и ломаются, если вы реализуете это в категории.
Clafou
7
Этот метод не работает в iOS8 при попытке удалить ячейку в режиме редактирования. SetFrame вызывается при входе / выходе из режима редактирования, поэтому ячейка продолжает сжиматься. Любое решение для этого?
Джон Баум
3
@JohnBaum, это может помочь (по крайней мере, в моем случае это работает): stackoverflow.com/questions/25911484/ios-8-cell-resizing/…
HashtagMarkus
2
Это решение поистине находка. На случай, если кому-то интересно, как сделать то же самое в Swift
reddit.com/r/swift/comments/2fr849/…
16

Чтобы сделать это в Swift, который не предоставляет методов для установки переменных, вам придется переопределить установщик для frame. Первоначально опубликовано (по крайней мере, там, где я его нашел) здесь

override var frame: CGRect {
    get {
        return super.frame
    }
    set (newFrame) {
        let inset: CGFloat = 15
        var frame = newFrame
        frame.origin.x += inset
        frame.size.width -= 2 * inset
        super.frame = frame
    }
}
JuJoDi
источник
Работает для swift
Саймон Макнил
9

Если ничего не работает, вы можете попробовать это

Сделайте цвет фона ячейки прозрачным, а затем поместите изображение ячейки нужного размера. Если вы хотите отобразить текст в этой ячейке, поместите метку над изображением. Не забудьте также установить цвет фона метки на прозрачный цвет.

включите меня
источник
8

Я обнаружил, что принятое решение не работает при вращении. Чтобы получить UITableViewCells с фиксированной шириной и гибкими полями, я просто адаптировал приведенное выше решение к следующему:

- (void)setFrame:(CGRect)frame {

    if (self.superview) {
        float cellWidth = 500.0;
        frame.origin.x = (self.superview.frame.size.width - cellWidth) / 2;
        frame.size.width = cellWidth;
    }

    [super setFrame:frame];
}

Метод вызывается всякий раз, когда устройство вращается, поэтому ячейки всегда будут по центру.

Грэм
источник
0

Есть метод, который вызывается при повороте экрана: viewWillTransitionToSize

Здесь вы должны изменить размер рамки. См. Пример. При необходимости измените координаты фрейма.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        int x = 0;
        int y = 0;
        self.tableView.frame = CGRectMake(x, y, 320, self.tableView.frame.size.height);
    }];
}
Парень
источник
-2

я делаю это в

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    CGFloat tableBorderLeft = self.view.frame.origin.x + 10;
    CGFloat tableBorderRight = self.view.frame.size.width - 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x = tableBorderLeft; 
    tableRect.size.width = tableBorderRight; 
    tableView.frame = tableRect;
}

И это сработало для меня

Lều Đức Quý
источник
-6

В файле .h добавьте делегата UITableViewDataSource.

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    return size;
}
bharath gangupalli
источник
4
Он хочет установить ширину, а не высоту
Кристофер Пикслей
ой ой. извиняюсь за неудобства.
bharath gangupalli
Вы неправильно поняли вопрос, и вы ответили на высоту, и вы знаете, что она работает для меня, потому что я ищу высоту, а не ширину .. спасибо за ответ
Pooja