J'essaie de créer une vue d'en-tête pour mon uiTableView (pas un en-tête de section, je les ai déjà.) J'ai configuré un XIB dans le générateur d'interface. Toutes les connexions sont raccordées et tout fonctionne à merveille ... sauf que la table ne lui laisse pas assez de place! Mon problème est que le haut de la table chevauche un peu l'en-tête de la table.
Mon XIB est configuré avec la lecture automatique pour tous les boutons et IB est heureux que les contraintes ne soient pas en conflit/ambiguë. La vue est définie sur Taille libre, ce qui dans mon cas a finalement été de 320 x 471. Ensuite, dans les contraintes relatives à la vue, j'ai défini une taille intrinsèque pour la vue identique.
Maintenant cela fonctionne parfaitement avec ma table. Tout a l'air super. Mais si je modifie manuellement l'une des polices dans la vue d'en-tête avec du code, la disposition rend la vue plus grande et se termine sous mon tableau.
Des idées sur la manière de faire en sorte que tableviewcontroller laisse suffisamment de place pour la vue en-tête après la définition des polices et des tailles? J'espère que j'ai eu du sens en expliquant cela.
Remarque: une version de Swift 3+ est disponible ici: https://Gist.github.com/marcoarment/1105553afba6b4900c10#gistcomment-1933639
L'idée est de calculer la hauteur de l'en-tête à l'aide de systemLayoutSizeFittingSize:targetSize
.
Retourne la taille de la vue qui satisfait les contraintes qu'elle contient . Détermine la taille optimale de la vue en tenant compte de toutes les contraintes détient et ceux de ses sous-vues.
Après avoir modifié la hauteur de l'en-tête, il est nécessaire de réaffecter la propriété tableHeaderView
pour ajuster les cellules du tableau.
Sur la base de cette réponse: Utilisation de la disposition automatique dans UITableView pour des dispositions de cellules dynamiques et des hauteurs de rangées variables
- (void)sizeHeaderToFit
{
UIView *header = self.tableView.tableHeaderView;
[header setNeedsLayout];
[header layoutIfNeeded];
CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect frame = header.frame;
frame.size.height = height;
header.frame = frame;
self.tableView.tableHeaderView = header;
}
J'ai rencontré un problème similaire lorsque j'essayais de définir l'en-tête de la vue tableau sur une vue personnalisée définie avec la présentation automatique à l'aide du générateur d'interface.
Quand j’ai fait cela, j’aurais trouvé qu’il serait masqué par un en-tête de section.
Mon travail consistait à utiliser une "vue factice" comme vue d'en-tête de tableau, puis à ajouter ma vue personnalisée à cette vue factice en tant que sous-vue. Je pense que cela permet à la disposition automatique de configurer l'apparence en fonction des contraintes et du cadre de la vue contenant. Ce n'est probablement pas aussi élégant que la solution de vokilam, mais cela fonctionne pour moi.
CGRect headerFrame = CGRectMake(0, 0, yourWidth, yourHeight);
UIView *tempView = [[UIView alloc] initWithFrame:headerFrame];
[tempView setBackgroundColor:[UIColor clearColor]];
YourCustomView *customView = [[YourCustomView alloc] initWithFrame: headerFrame];
[tempView addSubview:movieHeader];
self.tableView.tableHeaderView = tempView;
Parce que votre tableHeaderView
est sous la forme xib
avec mise en page automatique, les contraintes de votre coutume headerView
et de superView
sont inconnues. Vous devez ajouter le constraints
de votre coutume headerView
:
1.in viewDidLLoad
Affectez votre headerView personnalisé à la tableHeaderView de la table.
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *yourHeaderView = [[[NSBundle mainBundle] loadNibNamed:@"yourHeaderView" owner:nil options:nil] objectAtIndex:0];
//important:turn off the translatesAutoresizingMaskIntoConstraints;Apple documents for details
yourHeaderView.translatesAutoresizingMaskIntoConstraints = NO;
self.tableView.tableHeaderView = yourHeaderView;
}
2.in - (void) updateViewConstraints, ajoutez les contraintes essentielles de votre headerView personnalisé
- (void)updateViewConstraints
{
NSDictionary *viewsDictionary = @{@"headerView":yourHeaderView};
NSArray *constraint_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]"
options:0
metrics:nil
views:viewsDictionary];
NSArray *constraint_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(320)]"
options:0
metrics:nil
views:viewsDictionary];
[self.headerView addConstraints:constraint_H];
[self.headerView addConstraints:constraint_V];
NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]"
options:0
metrics:nil
views:viewsDictionary];
NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]"
options:0
metrics:nil
views:viewsDictionary];
[self.tableView addConstraints:constraint_POS_V];
[self.tableView addConstraints:constraint_POS_H];
[super updateViewConstraints];
}
OK! PS: voici le document associé: Redimensionnement des vues du contrôleur de vues
Voici ce qui a résolu mon problème:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
sizeHeaderToFit()
}
private func sizeHeaderToFit() {
if let headerView = tableView.tableHeaderView {
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
var newFrame = headerView.frame
// Needed or we will stay in viewDidLayoutSubviews() forever
if height != newFrame.size.height {
newFrame.size.height = height
headerView.frame = newFrame
tableView.tableHeaderView = headerView
}
}
}
J'ai trouvé cette solution quelque part et j'ai travaillé comme un charme, je ne me souviens plus où.
J'ai trouvé la réponse de vokilam au travail formidable. Voici sa solution dans Swift.
func sizeHeaderToFit() {
guard let header = tableView.tableHeaderView else { return }
header.setNeedsLayout()
header.layoutIfNeeded()
let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
header.frame.size.height = height
tableView.tableHeaderView = header
}
Les autres réponses m'ont orienté dans la bonne direction pour obtenir le redimensionnement approprié de tableHeaderView. Cependant, je devenais un écart entre l'en-tête et les cellules de tableView. Cela pourrait également entraîner le chevauchement de vos cellules avec votre en-tête, selon que l'en-tête s'agrandit ou diminue.
Je suis parti de ça:
tableView.reloadData()
let height = tableViewHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
tableView.tableHeaderView?.frame.size.height = height
Pour corriger le décalage/chevauchement, tout ce que je devais faire était de déplacer tableView.reloadData () après avoir défini la nouvelle hauteur plutôt qu'avant.
Pour ça:
let height = tableViewHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
tableView.tableHeaderView?.frame.size.height = height
tableView.reloadData()
Combinaison des réponses de @SwiftArchitect, @vokilam et @mayqiyue et utilisation d'une variable tableHeaderView
créée par programme au lieu d'une pointe (bien que je ne vois aucune raison pour laquelle cela ne fonctionnerait pas avec une pointe), sous iOS 10.x/Xcode 8.2.1, voici ce que j'ai en train de travailler:
Créez la vue dans les méthodes -viewDidLoad
ou -init
de votre contrôleur de vue, ou partout où vous utilisez la vue tableau:
MyCustomTableHeaderView *myCustomTableHeaderView = [[MyCustomTableHeaderView alloc] init]; // Don't set its frame
myCustomTableHeaderView.translatesAutoresizingMaskIntoConstraints = NO;
self.myTableView.tableHeaderView = myCustomTableHeaderView;
self.myCustomTableHeaderView = myCustomTableHeaderView; // We set and update our constraints in separate methods so we store the table header view in a UIView property to access it later
Où que vous configuriez les contraintes de votre vue d'en-tête personnalisé (cela peut être dans `updateConstraints mais cette méthode peut être appelée plusieurs fois):
// We use Pure Layout in our project, but the workflow is the same:
// Set width and height constraints on your custom view then pin it to the top and left of the table view
// Could also use VFL or NSLayoutConstraint methods
[self.myCustomTableHeaderView autoSetDimension:ALDimensionWidth toSize:CGRectGetWidth(self.superview.frame)]; // Width set to tableview's width
[self.myCustomTableHeaderView autoSetDimension:ALDimensionHeight toSize:height]; // Whatever you want your height to be
[self.myCustomTableHeaderView autoPinEdgeToSuperviewEdge:ALEdgeTop];
[self.myCustomTableHeaderView autoPinEdgeToSuperviewEdge:ALEdgeLeft];
// This is important
[self.myCustomTableHeaderView layoutIfNeeded]; // We didn't need to call -setNeedsLayout or reassign our custom header view to the table view's tableHeaderView property again, as was noted in other answers
Dans mon cas, systemLayoutSizeFittingSize
renvoie une taille incorrecte, car l'une des sous-vues utilise le format d'image (largeur en hauteur) 4: 1.
Après avoir modifié la valeur de contrainte de hauteur constante (100), il commence à fonctionner comme prévu.
sizeHeaderToFit
suggéré par @vokilam n'a pas fonctionné pour moi.
Ce qui a fonctionné est une version modifiée de @mayqiyue, invoquée pendant viewDidLoad
, hauteur câblée, largeur égale à la vue tableau.
// Anchor the headerview, and set width equal to superview
NSDictionary *viewsDictionary = @{@"headerView":self.tableView.tableHeaderView,
@"tableView":self.tableView};
[self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]"
options:0
metrics:nil
views:viewsDictionary]];
[self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]"
options:0
metrics:nil
views:viewsDictionary]];
[self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(==tableView)]"
options:0
metrics:nil
views:viewsDictionary]];
[self.tableView.tableHeaderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]"
options:0
metrics:nil
views:viewsDictionary]];
La réponse de @rmigneco a fonctionné pour moi, alors voici la version Swift:
let headerFrame = CGRectMake(0, 0, 100, 1);
let tempView = UIView(frame: headerFrame);
tempView.backgroundColor = UIColor.clearColor()
let yourCustomView = CustomView(frame: headerFrame)
tempView.addSubview(yourCustomView)
self.tableView.tableHeaderView = tempView
Le code ci-dessous a fonctionné pour moi: - Ajoutez-le dans votre classe UIView -
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.frame = CGRectMake(0, 0, self.frame.size.width, [[self class] height]);
}
return self;
}