Je ne parviens pas à redimensionner une tableHeaderView. C'est simple, ça ne marche pas.
1) Créez un UITableView et UIView (100 x 320 px);
2) Définissez UIView comme tableHeaderView de UITableView;
3) Construire et aller. Tout va bien.
Maintenant, je veux redimensionner la tableHeaderView, alors j'ajoute ce code dans viewDidLoad:
self.tableView.autoresizesSubviews = YES;
self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;
CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;
La hauteur de la tableHeaderView doit apparaître avec 200, mais avec 100.
Si j'écris:
self.tableView.autoresizesSubviews = YES;
CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;
self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;
Ensuite, ça commence avec 200 de hauteur, comme je veux. Mais je veux pouvoir le modifier en cours d'exécution.
J'ai aussi essayé cela, sans succès:
self.tableView.autoresizesSubviews = YES;
self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;
CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;
[self.tableView.tableHeaderView setNeedsLayout];
[self.tableView.tableHeaderView setNeedsDisplay];
[self.tableView setNeedsLayout];
[self.tableView setNeedsDisplay];
Le point ici est: Comment redimensionnons-nous une tableHeaderView au runtime ???
Quelqu'un a-t-il pu faire cela?
Merci
je suis
FYI: Cela a fonctionné en modifiant la tableHeaderView et en la réinitialisant. Dans ce cas, je suis en train d'ajuster la taille de la tableHeaderView lorsque le chargement de la sous-vue UIWebView est terminé.
[webView sizeToFit];
CGRect newFrame = headerView.frame;
newFrame.size.height = newFrame.size.height + webView.frame.size.height;
headerView.frame = newFrame;
[self.tableView setTableHeaderView:headerView];
Cette réponse est ancienne et apparemment ne fonctionne pas sur iOS 7 et supérieur.
J'ai rencontré le même problème et je voulais aussi que les modifications s'animent. J'ai donc créé une sous-classe d'UIView pour ma vue d'en-tête et ajouté ces méthodes:
- (void)adjustTableHeaderHeight:(NSUInteger)newHeight{
NSUInteger oldHeight = self.frame.size.height;
NSInteger originChange = oldHeight - newHeight;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
self.frame = CGRectMake(self.frame.Origin.x,
self.frame.Origin.y,
self.frame.size.width,
newHeight);
for (UIView *view in [(UITableView *)self.superview subviews]) {
if ([view isKindOfClass:[self class]]) {
continue;
}
view.frame = CGRectMake(view.frame.Origin.x,
view.frame.Origin.y - originChange,
view.frame.size.width,
view.frame.size.height);
}
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
[(UITableView *)self.superview setTableHeaderView:self];
}
Cela anime essentiellement toutes les sous-vues de UITableView qui ne sont pas du même type que la classe appelante. À la fin de l'animation, il appelle setTableHeaderView sur le superview (le UITableView) - sans cela, le contenu du UITableView reviendra en arrière lors du prochain défilement de l'utilisateur. La seule limitation que j'ai trouvée jusqu'à présent est que si l'utilisateur tente de faire défiler UITableView pendant le déroulement de l'animation, le défilement s'animera comme si la vue d'en-tête n'avait pas été redimensionnée (ce n'est pas grave si l'animation est rapide).
Si vous souhaitez animer les modifications de manière conditionnelle, vous pouvez procéder comme suit:
- (void) showHeader:(BOOL)show animated:(BOOL)animated{
CGRect closedFrame = CGRectMake(0, 0, self.view.frame.size.width, 0);
CGRect newFrame = show?self.initialFrame:closedFrame;
if(animated){
// The UIView animation block handles the animation of our header view
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// beginUpdates and endUpdates trigger the animation of our cells
[self.tableView beginUpdates];
}
self.headerView.frame = newFrame;
[self.tableView setTableHeaderView:self.headerView];
if(animated){
[self.tableView endUpdates];
[UIView commitAnimations];
}
}
Veuillez noter que l'animation est double:
tableHeaderView
. Ceci est fait en utilisant beginUpdates
et endUpdates
UIView
. Afin de synchroniser ces deux animations, la variable animationCurve
doit être définie sur UIViewAnimationCurveEaseInOut
et la durée sur 0.3
, ce qui semble être ce que UITableView utilise pour son animation.
J'ai créé un projet Xcode sur gihub, qui le fait . Consultez le projet ResizeTableHeaderViewAnimated
dans besi/ios-quickies
Je pense que cela devrait fonctionner si vous définissez la hauteur de myHeaderView comme suit:
CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;
self.tableView.tableHeaderView = myHeaderView;
Utiliser la solution @ garrettmoon ci-dessus jusqu'à iOS 7.
Voici une solution mise à jour basée sur @ garrettmoon:
- (void)adjustTableHeaderHeight:(NSUInteger)newHeight animated:(BOOL)animated {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:[CATransaction animationDuration]];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
self.frame = CGRectMake(self.frame.Origin.x,
self.frame.Origin.y,
self.frame.size.width,
newHeight);
[(UITableView *)self.superview setTableHeaderView:self];
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
[(UITableView *)self.superview setTableHeaderView:self];
}
Cela a fonctionné pour moi sur iOS 7 et 8. Ce code est exécuté sur le contrôleur de vue de table.
[UIView animateWithDuration:0.3 animations:^{
CGRect oldFrame = self.headerView.frame;
self.headerView.frame = CGRectMake(oldFrame.Origin.x, oldFrame.Origin.y, oldFrame.size.width, newHeight);
[self.tableView setTableHeaderView:self.headerView];
}];
C'est parce que le passeur de tableHeaderView.
Vous devez définir la hauteur UIView avant de définir tableHeaderView. (Ce serait beaucoup plus facile si Apple ouvrait ce cadre avec des sources ouvertes ...)
Sur iOS 9 et les versions antérieures, tableHeaderView
ne remettrait pas en page après le redimensionnement . Ce problème est résolu dans iOS 10.
Pour résoudre ce problème, faites-le simplement avec le code suivant:
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
Sur iOS 9.x, cela sur viewDidLoad
fonctionne parfaitement:
var frame = headerView.frame
frame.size.height = 11 // New size
headerView.frame = frame
headerView
est déclaré en tant que @IBOutlet var headerView: UIView!
et connecté au storyboard, où il est placé en haut de tableView, pour fonctionner en tant que tableHeaderView.
La définition de height pour la propriété tableView.tableHeaderView
dans viewDidLoad
semble ne pas fonctionner, la hauteur de la vue en-tête ne change toujours pas comme prévu.
Après avoir lutté contre ce problème pendant de nombreux essais. J'ai trouvé que vous pouvez modifier la hauteur en appelant la logique de création de la vue en-tête dans la méthode - (void)didMoveToParentViewController:(UIViewController *)parent
.
Ainsi, l'exemple de code ressemblerait à ceci:
- (void)didMoveToParentViewController:(UIViewController *)parent {
[super didMoveToParentViewController:parent];
if ( _tableView.tableHeaderView == nil ) {
UIView *header = [[[UINib nibWithNibName:@"your header view" bundle:nil] instantiateWithOwner:self options:nil] firstObject];
header.frame = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), HeaderViewHeight);
[_tableView setTableHeaderView:header];
}
}
Évidemment, à ce jour, Apple aurait dû implémenter UITableViewAutomaticDimension pour tableHeaderView & tableFooterView ...
Ce qui suit semble fonctionner pour moi en utilisant des contraintes de mise en page:
CGSize s = [ self systemLayoutSizeFittingSize : UILayoutFittingCompressedSize ];
CGRect f = [ self frame ];
f.size = s;
[ self setFrame : f ];
Cela s'applique uniquement lorsque vous utilisez la mise en page automatique et définissez translatesAutoresizingMaskIntoConstraints = false
sur une vue d'en-tête personnalisée.
La meilleure et la plus simple consiste à remplacer intrinsicContentSize
. En interne, UITableView
utilise intrinsicContentSize
pour décider de la taille de son en-tête/pied de page. Une fois que vous avez remplacé intrinsicContentSize
dans votre vue personnalisée, procédez comme suit:
invalidateIntrinsicContentSize()
tableView.setNeedsLayout()
et tableView.layoutIfNeeded()
Ensuite, l'en-tête/le pied de page de UITableView
sera mis à jour comme vous le souhaitez. Pas besoin de définir la vue nil ou réinitialiser.
Une chose vraiment intéressante pour le UITableView.tableHeaderView
ou le .tableFooterView
est que UIStackView
perd sa capacité à gérer son arrangedSubviews
. Si vous voulez utiliser UIStackView
en tant que tableHeaderView ou tableFooterView, vous devez incorporer stackView dans un UIView
et remplacer le UIView
's intrinsicContentSize
.
Si votre tableHeaderView est une webView à contenu réglable, vous pouvez essayer:
[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
self.webView.height = self.webView.scrollView.contentSize.height;
self.tableView.tableHeaderView = self.webView;
}
Je l'ai testé sur iOS9 et iOS11, a bien fonctionné.
J'ai trouvé que l'initialiseur initWithFrame d'un UIView ne respecte pas correctement le rect que je passe. J'ai donc fait ce qui suit parfaitement:
- (id)initWithFrame:(CGRect)aRect {
CGRect frame = [[UIScreen mainScreen] applicationFrame];
if ((self = [super initWithFrame:CGRectZero])) {
// Ugly initialization behavior - initWithFrame will not properly honor the frame we pass
self.frame = CGRectMake(0, 0, frame.size.width, 200);
// ...
}
}
L'avantage de ceci est qu'il est mieux encapsulé dans votre code d'affichage.
Je voulais une UITableView
avec une UISearchBar
comme en-tête de la table afin d'avoir une hiérarchie qui ressemble à ceci
UITableView
|
|--> UIView
| |--> UISearchBar
|
|--> UITableViewCells
Comme il a été indiqué ailleurs, si vous ne définissez pas TableViewHeader après l'avoir modifié, rien ne se passera.
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
searchBar.showsScopeBar = YES;
[UIView animateWithDuration:0.2f animations:^{
[searchBar sizeToFit];
CGFloat height = CGRectGetHeight(searchBar.frame);
CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = height;
self.tableHeaderView.frame = frame;
self.tableView.tableHeaderView = self.tableHeaderView;
}];
[searchBar setShowsCancelButton:YES animated:YES];
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
searchBar.showsScopeBar = NO;
[UIView animateWithDuration:0.f animations:^{
[searchBar sizeToFit];
CGFloat height = CGRectGetHeight(searchBar.frame);
CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = height;
self.tableHeaderView.frame = frame;
self.tableView.tableHeaderView = self.tableHeaderView;
}];
[searchBar setShowsCancelButton:NO animated:YES];
return YES;
}
J'ai implémenté le changement de hauteur animé de l'en-tête de la table pour passer à l'écran général lorsque vous appuyez dessus. Cependant, le code peut aider dans d'autres cas:
// Swift
@IBAction func tapped(sender: UITapGestureRecognizer) {
self.tableView.beginUpdates() // Required to update cells.
// Collapse table header to original height
if isHeaderExpandedToFullScreen {
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.scrollView.frame.size.height = 110 // original height in my case is 110
})
}
// Expand table header to overall screen
else {
let screenSize = self.view.frame // "screen" size
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.scrollView.frame.size.height = screenSize.height
})
}
self.tableView.endUpdates() // Required to update cells.
isHeaderExpandedToFullScreen= !isHeaderExpandedToFullScreen // Toggle
}
Si headerView personnalisé est conçu à l'aide de autolayout et que headerView doit être mis à jour après la récupération Web ou une tâche similaire paresseuse . Puis dans iOS-Swift j'ai procédé ainsi et mis à jour mon headerView avec le code ci-dessous:
//to reload your cell data
self.tableView.reloadData()
dispatch_async(dispatch_get_main_queue(),{
// this is needed to update a specific tableview's headerview layout on main queue otherwise it's won't update perfectly cause reloaddata() is called
self.tableView.beginUpdates()
self.tableView.endUpdates()
}