2010-10-20 12 views
3

J'ai actuellement une sous-classe UIView qui sert de vue d'en-tête pour mon UITableViewController. Toutes les sous-vues varient en taille selon les données récupérées pour un article particulier. LayoutSubViews est appelé pour l'UIView avant que je puisse déterminer la taille de chaque étiquette. Cela provoque un problème car j'ai défini la taille de la vue dans la méthode layoutSubViews. Comme il est appelé avant de configurer mes étiquettes, la hauteur des vues est toujours 0. Même après la configuration des étiquettes, j'appelle setNeedsLayout mais la taille de l'en-tête des vues de la table ne change pas.Redimensionnement d'une sous-classe UIView avec sous-vues de taille dynamique

Cela va créer mon TableHeaderView et définir le texte pour mes étiquettes.

TableHeaderView *tableHeaderView = [[TableHeaderView alloc] initWithFrame:CGRectZero]; 
    tableHeaderView.headerTitle.text = title; 
    tableHeaderView.headerOption1.text = headerOption1 
    tableHeaderView.headerOption2.text = headerOption2 
    tableHeaderView.headerOption3.text = headerOption3 

    [[self tableView] setTableHeaderView:tableHeaderView]; 

    [tableHeaderView setNeedsLayout]; 
    [tableHeaderView release]; 

Voici ma sous-classe UIView

- (id)initWithFrame:(CGRect)frame { 
    if ((self = [super initWithFrame:frame])) { 

    UIView *headerView = self; 

    self.headerTitle = [[UILabel alloc] initWithFrame:CGRectZero]; 
    self.headerTitle.numberOfLines = 3; 
    self.headerTitle.lineBreakMode = UILineBreakModeWordWrap; 
    [headerView addSubview:self.headerTitle]; 
    [self.headerTitle release]; 

    self.headerOption1 = [[UILabel alloc] initWithFrame:CGRectZero]; 
    self.headerOption1.numberOfLines = 2; 
    self.headerOption1.lineBreakMode = UILineBreakModeWordWrap; 
    [headerView addSubview:self.headerOption1]; 
    [self.headerOption1 release]; 
} 
return self; 
} 

- (void)layoutSubviews { 

[super layoutSubviews]; 

CGSize maxLabelSize; 

/*...*/ 

[self.headerTitle setFrame:CGRectMake(10.0f, 10.0f, titleWidth, titleHeight)]; 

/*...*/ 

[self.headerOption1 setFrame:CGRectMake(10.0f, (self.headerTitle.frame.origin.y + self.headerTitle.bounds.size.height + 2.5f), pubWidth, pubHeight)]; 

    /*...*/ 
    [self setFrame:CGRectMake(0.0f, 0.0f, 320.0f, tableHeaderHeight)]; 
} 

La deuxième fois que layoutSubviews est appelé toutes les sous-vues obtenir taille correcte, sauf pour la vue elle-même (tableHeaderHeight a la bonne hauteur). Ne devrais-je pas redimensionner la vue de cette méthode? Y a-t-il une meilleure approche à cela?

Répondre

3

Vous devrez probablement remplacer sizeThatFits: dans votre sous-classe UIView pour renvoyer la taille appropriée en fonction de votre disposition.

utiliser comme ceci:

TableHeaderView *tableHeaderView = [[TableHeaderView alloc] initWithFrame:CGRectZero]; 
tableHeaderView.headerTitle.text = title; 
tableHeaderView.headerOption1.text = headerOption1 
tableHeaderView.headerOption2.text = headerOption2 
tableHeaderView.headerOption3.text = headerOption3 

tableHeaderView.frame = (CGRect){ 
    .origin = tableHeaderView.frame.origin, 
    .size = [tableHeaderView sizeThatFits:CGSizeZero], 
}; 

[[self tableView] setTableHeaderView:tableHeaderView]; 

[tableHeaderView setNeedsLayout]; // I don't think you need this anymore. 
[tableHeaderView release]; 
+0

J'ai essayé votre suggestion pour appeler [tableHeaderView sizeToFit] après avoir configuré le contenu des étiquettes, mais je pense que mon vrai problème ici est qu'une fois que setTableHeaderView: tableHeaderView est appelée, la taille de l'en-tête de table ne changera pas. [tableHeaderView setNeedsLayout] n'appelle pas la méthode layoutSubViews tant que la vue n'a pas été définie sur l'en-tête. Donc, quelle que soit la taille que j'ai définie pour la vue, cela n'affecte pas la taille de l'en-tête. – avenged

+1

Je n'ai pas dit de l'appeler, vous devez ** mettre en place ** sizeThatFits sur votre sous-classe et retourner la taille que vous voulez. –

+0

Désolé, je voulais d'abord dire que j'ai implémenté sizeThatFits pour renvoyer la taille correcte de l'en-tête. Le problème est qu'une fois que sizeToFit a été appelé (je suppose que vous voulez que je l'appelle après la configuration des étiquettes), tableHeaderView a déjà été défini sur l'en-tête des vues de la table. – avenged

1

Si je remplace

[tableHeaderView setNeedsLayout]; 

avec

[tableHeaderView layoutSubviews]; 

la vue d'en-tête est correctement dimensionné. Cela se produit car setNeedsLayout n'appelle pas layoutSubViews tant que la vue n'a pas été définie sur l'en-tête. Si j'appelle directement layoutSubViews, layoutSubviews sera appelé avant de définir la vue.

Mais j'ai entendu dans le passé que l'appel direct de layoutSubviews n'est pas une bonne idée, est-ce aussi vrai pour ce cas?

+0

Call layoutIfNeeded après setNeedsLayout. – hybridcattt