UITableViewCell. Как я программно выравниваю textLabel к вершине?

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

Спасибо,
Doug

9
задан nikc.org 2 August 2010 в 03:32
поделиться

2 ответа

В документах описывается - [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. создайте два собственных UILabel для предоставления текста и подробного текста,
    2. добавьте их в self.contentView и
    3. переопределите -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 вы бы проигнорировали встроенные текстовые метки и использовали свои собственные пользовательские UILabels.Вы полностью контролируете их размещение в прямоугольнике содержимого ячейки табличного представления.

Я многое опускаю. Создавая собственный макет с текстовыми метками, вам нужно подумать:

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

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

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

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

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

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

24
ответ дан 4 December 2019 в 08:14
поделиться

Макеты 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
}
0
ответ дан 4 December 2019 в 08:14
поделиться