2010-07-28 4 views
9

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

Спасибо,
Doug

+0

Это вопрос, связанный с Iphone? –

+0

Да. UITableViewCell вместе с UITableView и UITableViewController уникальны для iPhone OS. Нет? – dugla

+1

Тогда почему не вопрос с меткой iphone? Пожалуйста, позаботьтесь о мечении, чтобы другие могли воспользоваться вашими вопросами. –

ответ

24

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

В related SO question, в Reco чтобы избежать # 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. Вы берете полный контроль над позиционированием их в пределах содержимого rect ячейки таблицы.

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

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

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

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

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

  • Как обращаться с -viewDidLoad/-viewDidUnload.

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

+0

Спасибо за супер тщательное освещение макетов. Не думал, что это так просто в использовании. Круто. – dugla

+0

Отличный ответ, но я думаю, вы должны переписать initWithStyle: reuseIdentifier: вместо метода initWithFrame:. – Rodrigo

+1

Я не уверен, что есть много преимуществ для переопределения 'initWithStyle: reuseIdentifier:' vs 'initWithFrame'. Тем более, что после инициализации может быть явно задан параметр reuseIdentifier. Для подклассов UITableViewCell, возможно, -initWithReuseIdentifier: был бы более удобным назначенным инициализатором. Для ячеистых подклассов игнорирование свойства 'style'/принятие значения по умолчанию кажется лучшим. Тем не менее, вы можете определить свою собственную константу стиля. Но кто бы это использовал? –

0

Макет UITableViewCell TextLabel и detailTextLabel не непосредственно изменяемым, за исключением того, выбирая один из определенных стилей, предоставляемых 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

layoutSubviews - это метод, который я никогда не переопределял и плохо документирован. Не могли бы вы немного разобраться? Благодарю. – dugla

2

Следующий метод в вашем 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]; 
} 
Смежные вопросы