UITableViewCell. Как программно выровнять textLabel по верху? - PullRequest
9 голосов
/ 28 июля 2010

По умолчанию экземпляр UITableViewCell размещает пару меток textLabel / detailTextLabel в центре своего родительского представления. Я предпочитаю выравнивать пару по верху ячейки. Как мне сделать это программно?

Спасибо
Дуг

Ответы [ 3 ]

24 голосов
/ 31 июля 2010

Документы описывают - [UIView layoutSubviews] как

"Overridden by subclasses to layout subviews when layoutIfNeeded is invoked. The default implementation of this method does nothing."

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

Поскольку реализация UIView ничего не делает (и я предполагаю, что то же самое для UIControl), вы получаете полную свободу творчества, чтобы размещать подвиды подкласса UIView в любом месте.

При создании подкласса UITableViewCell у вас есть несколько вариантов:

  1. Переопределить -layoutSubviews и
    1. манипулировать положением встроенных представлений textLabel и -detailLabel.
  2. Переопределить -viewDidLoad,
    1. создайте два собственных UILabels для предоставления текста и подробного текста,
    2. добавьте их в self.contentView и
    3. override -layoutSubviews для управления положением ваших пользовательских представлений UILabel

В связанном SO вопросе рекомендуется избегать # 1 манипулирования встроенными textLabel и detailTextLabel.

Более надежной ставкой было бы сделать что-то вроде этого:


@interface MyTableViewCell : UITableViewCell {
    UILabel *myTextLabel;
    UILabel *myDetailTextLabel;
}
// ... property declarations
@end

@implementation MyTableViewCell 
@synthesize myTextLabel, myDetailTextLabel;

- (id) initWithFrame: (CGRect)frame {
    self = [super initWithFrame: frame];
    if (self) {
        myTextLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
        [self.contentView addSubview: myTextLabel];

        myDetailTextLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
        [self.contentView addSubview: myDetailTextLabel];
    }
    return self;
}

- (void) dealloc {
    [myTextLabel release];
    [myDetailTextLabel release];
    [super dealloc];
}

- (void) layoutSubviews {

    // Let the super class UITableViewCell do whatever layout it wants. 
    // Just don't use the built-in textLabel or detailTextLabel properties
    [super layoutSubviews]; 

    // Now do the layout of your custom views

    // Let the labels size themselves to accommodate their text
    [myTextLabel sizeToFit];
    [myDetailTextLabel sizeToFit];

    // Position the labels at the top of the table cell
    CGRect newFrame = myTextLabel.frame;
    newFrame.origin.x = CGRectGetMinX (self.contentView.bounds);
    newFrame.origin.y = CGRectGetMinY (self.contentView.bounds);
    [myTextLabel setFrame: newFrame];

    // Put the detail text label immediately to the right 
        // w/10 pixel gap between them
    newFrame = myDetailTextLabel.frame;
    newFrame.origin.x = CGRectGetMaxX (myTextLabel.frame) + 10.;
    newFrame.origin.y = CGRectGetMinY (self.contentView.bounds);
    [myDetailTextLabel setFrame: newFrame];
}

@end

В MyTableViewCell вы игнорируете встроенные текстовые метки и используете свои собственные пользовательские метки UILabel. Вы полностью контролируете их размещение в прямоугольнике содержимого ячейки табличного представления.

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

  • Выяснение собственного алгоритма компоновки.

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

  • Сохранение пользовательских меток в представлении содержимого.

    В -layoutSubviews вы, возможно, захотите, чтобы логика поддерживала размер и расположение пользовательских UILabel таким образом, чтобы они не выходили за границы прямоугольника содержимого. С моей наивной логикой компоновки любой длинный текст, помещенный в UILabel (или в оба), может привести к тому, что метки будут расположены прямо за пределами представления содержимого.

  • Как обрабатывать -viewDidLoad / -viewDidUnload.

    Как написано выше, этот подкласс не обрабатывает загрузку с пера. Возможно, вы захотите использовать IB для разметки вашей ячейки, и если вам это нужно, вам нужно подумать о -viewDidLoad / -viewDidUnload / -initWithCoder:

2 голосов
/ 17 марта 2012

Следующий метод в вашем подклассе UITableViewCell должен быстро и точно выровнять textLabel и detailTextLabel по верху ячейки (кивок коду Билла) без добавления каких-либо пользовательских представлений.

- (void) layoutSubviews 
{
    [super layoutSubviews]; 

    // Set top of textLabel to top of cell
    CGRect newFrame = self.textLabel.frame;
    newFrame.origin.y = CGRectGetMinY (self.contentView.bounds);
    [self.textLabel setFrame:newFrame];

    // Set top of detailTextLabel to bottom of textLabel
    newFrame = self.detailTextLabel.frame;
    newFrame.origin.y = CGRectGetMaxY (self.textLabel.frame);
    [self.detailTextLabel setFrame:newFrame];
}
0 голосов
/ 30 июля 2010

Макет textLabel и detailTextLabel UITableViewCell не может быть изменен напрямую, за исключением выбора одного из определенных стилей, предоставляемых API.

typedef enum {
   UITableViewCellStyleDefault,
   UITableViewCellStyleValue1,
   UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
} UITableViewCellStyle;

Если вы хотите настроить макет UITableViewCell, вам необходимосоздайте подкласс и переопределите метод -layoutSubviews.


- (void) layoutSubviews {
   // [super layoutSubViews]; // don't invoke super

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