web-dev-qa-db-fra.com

La propriété tableFooterView ne corrige pas le pied de page en bas de la vue de table

Je mets une vue de pied de page dans la méthode viewDidLoad:

UIView *fView = [[UIView alloc] initWithFrame:CGRectMake(0, 718, 239, 50)];
fView.backgroundColor =[UIColor yellowColor];
self.table.tableFooterView = fView;

Malheureusement, le pied de page ne dessine pas dans le (x,y) spécifié ci-dessus, mais il reste avec les cellules, donc si la vue de table a 4 cellules, le pied de page sera dessiné dans la 5ème cellule.

J'ai même essayé la méthode du protocole, tableView:viewForFooterInSection

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{

UIView *fView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 239, 50)];
fView.backgroundColor =[UIColor yellowColor];
    return fView;
}

le problème n'est pas résolu, je suis sûr que la propriété tableFooterView devrait correspondre à la vue de pied de page au bas de la vue de la table mais je ne sais pas ce que je peux manquer ici? Merci d'avance.

31
Malloc

Étant donné que votre objectif est d'avoir un pied de page qui reste fixe en bas de l'écran et de ne pas faire défiler le tableau, vous ne pouvez pas utiliser un pied de page de vue de tableau. En fait, vous ne pouvez même pas utiliser un UITableViewController.

Vous devez implémenter votre contrôleur de vue en tant que UIViewController. Ensuite, vous ajoutez votre propre vue de table en tant que sous-vue. Vous ajoutez également votre pied de page en tant que sous-vue de la vue du contrôleur de vue, et non de la vue de table. Assurez-vous de dimensionner la vue de table de sorte que son bas se trouve en haut de la vue de pied de page.

Vous devrez rendre votre contrôleur de vue conforme aux protocoles UITableViewDataSource et UITableViewDelegate et tout connecter pour répliquer les fonctionnalités de UITableViewController.

53
rmaddy

Une vue de pied de page sera toujours ajoutée au bas du contenu.
Cela signifie qu'un pied de page de section sera ajouté sous les cellules d'une section, une vue de pied de page de tableau au bas de toutes les sections, quelle que soit la position que vous définissez dans votre vue.

Si vous souhaitez ajouter un contenu "statique", vous devriez envisager d'ajouter une vue en dehors de la vue de table (superview) - ce qui n'est pas possible si vous utilisez UITableViewController - ou vous utilisez [self.table addSubView:view] et ajustez la position/transformation à la propriété contentOffset de la vue tableau dans scrollViewDidScroll: méthode déléguée (UITableView est une sous-classe de UIScrollView donc vous obtenez également ses appels de délégué) comme dans ce code:

@implementation YourTableViewController {
    __weak UIView *_staticView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UIView *staticView = [[UIView alloc] initWithFrame:CGRectMake(0, self.tableView.bounds.size.height-50, self.tableView.bounds.size.width, 50)];
    staticView.backgroundColor = [UIColor redColor];
    [self.tableView addSubview:staticView];
    _staticView = staticView;
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 50, 0);
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    _staticView.transform = CGAffineTransformMakeTranslation(0, scrollView.contentOffset.y);
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // this is needed to prevent cells from being displayed above our static view
    [self.tableView bringSubviewToFront:_staticView];
}

...
34
Martin Ullrich

Une autre façon consiste à utiliser UITableViewController dans un storyboard et à l'intégrer dans un UIViewController en tant que vue de conteneur. Vous pouvez ensuite utiliser la mise en page automatique pour définir la relation entre le pied de page et la vue du conteneur qui contient le UITableView

14
cohen72

Si votre contrôleur de vue de tableau ou de tableau est encapsulé par un contrôleur de navigation, envisagez d'utiliser la barre d'outils UIT du contrôleur de navigation. Il collera toujours au fond.

[self.navigationController setToolbarHidden:NO];
8
Steve Moser

J'ai pu obtenir une étiquette à fixer au bas de mon UITableViewController statique. Pas la solution parfaite pour tous les scénarios, mais a fonctionné pour mes besoins simples.

UIView* v = [[UIView alloc] initWithFrame:self.view.bounds];
CGFloat labelHeight = 30;
CGFloat padding = 5;
UILabel* l = [[UILabel alloc] initWithFrame:CGRectMake(0, v.frame.size.height - labelHeight - padding, self.view.frame.size.width, labelHeight)];
l.text = @"Hello World";
[v addSubview:l];
[self.tableView setBackgroundView:v];
3
JordanC

Il semble que quelque chose de similaire à ci-dessous fonctionne très bien:

import PlaygroundSupport
import UIKit

let testVC = UITableViewController(style: .grouped)
testVC.view.frame = CGRect(x: 0, y: 0, width: 400, height: 700)
testVC.view.backgroundColor = .white

class TableViewDataSourceDelegate : NSObject {
    var rows = 2
}

extension TableViewDataSourceDelegate : UITableViewDataSource, UITableViewDelegate {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return rows
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
        cell.backgroundColor = .red
        return cell
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {

        let tableViewHeight = tableView.bounds.size.height
        let varticalMargin: CGFloat
        if #available(iOS 11.0, *) {
            varticalMargin = tableView.directionalLayoutMargins.bottom + tableView.directionalLayoutMargins.top
        } else {
            varticalMargin = tableView.layoutMargins.bottom + tableView.layoutMargins.top
        }

        let verticalInset: CGFloat
        if #available(iOS 11.0, *) {
            verticalInset = tableView.adjustedContentInset.bottom + tableView.adjustedContentInset.top
        } else {
            verticalInset = tableView.contentInset.bottom + tableView.contentInset.top
        }
        let tableViewContentHeight = tableView.contentSize.height - varticalMargin


        let height: CGFloat
        if #available(iOS 11.0, *) {
            let verticalSafeAreaInset = tableView.safeAreaInsets.bottom + tableView.safeAreaInsets.top
            height = tableViewHeight - tableViewContentHeight - verticalInset - verticalSafeAreaInset
        } else {
            height = tableViewHeight - tableViewContentHeight - verticalInset
        }

        if (height < 0) {
            return 0
        } else {
            return height
        }
    }

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let extraButtonSpace = UIView()
        extraButtonSpace.backgroundColor = .clear
        return extraButtonSpace
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.row == 0 {
            tableView.beginUpdates()
            rows += 1
            tableView.insertRows(at: [indexPath], with: .automatic)
            tableView.endUpdates()
        } else if indexPath.row == 1 {
            tableView.beginUpdates()
            rows -= 1
            tableView.deleteRows(at: [indexPath], with: .automatic)
            tableView.endUpdates()
        } else {
            tableView.beginUpdates()
            tableView.endUpdates()
        }
    }
}


let controller = TableViewDataSourceDelegate()
testVC.tableView.delegate = controller
testVC.tableView.dataSource = controller
testVC.tableView.reloadData()

let extraButtonSpace = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 80))
extraButtonSpace.backgroundColor = .yellow
testVC.tableView.tableFooterView = extraButtonSpace

PlaygroundPage.current.liveView = testVC.view

Screen from playground

3
KaQu

Si vous souhaitez rendre le pied de page fixe en bas, vous devez créer un pied de page personnalisé et modifier le cadre du pied de page lorsque la taille du contenu de tableView change:

-(void)changeCustomTableFooterYPositionWithTableFrame:(CGRect)tableFrame tableContentSize: (CGSize) tableContentSize {
    CGFloat originalTableViewTopEdgeInset = self.tableView.contentInset.top;
    CGFloat originalTableViewBottomEdgeInset = self.tableView.contentInset.bottom - self.tableFooterView.frame.size.height;

    CGFloat footerViewYPositionByContentSize = tableContentSize.height;
    CGFloat footerViewYPositionByTableSize = tableFrame.size.height - self.tableFooterView.frame.size.height - originalTableViewTopEdgeInset - originalTableViewBottomEdgeInset;
    CGFloat tableFooterViewYPosition = MAX(footerViewYPositionByContentSize, footerViewYPositionByTableSize);

    self.tableFooterView.frame = CGRectMake(self.tableFooterView.frame.Origin.x, tableFooterViewYPosition, self.customTableFooterView.frame.size.width, self.customTableFooterView.frame.size.height);
}

Pour détecter la modification de contentSize, ajoutez un observateur à contentSize:

 [self addObserver: self forKeyPath: @"tableView.contentSize" options: NSKeyValueObservingOptionNew + NSKeyValueObservingOptionOld context: ContentSizeContext];

N'oubliez pas de changer tableView.edgeInsets lors de l'insertion du pied de page:

self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, self.tableView.contentInset.bottom + self.customTableFooterView.frame.size.height, self.tableView.contentInset.right);

Vous pouvez voir la classe héritée et l'exemple sur le lien ci-dessous: TableViewWithFooterAtBottom

1
NoN

Ce qui suit est la solution à ce problème de pied de page, lorsque nous ne voulons pas que le pied de page reste tout le temps en bas, AKA. il ne reste en bas que lorsqu'il n'y a pas suffisamment de lignes pour remplir l'écran ou lorsque l'utilisateur fait défiler l'écran vers le bas.

Ajoutez votre self.footerView À votre self.tableView Comme sous-vue sur -viewDidLoad: Ou quelque part comme ça, puis définissez le délégué pour self.tableView, Mettez à jour l'encart de contenu de la vue de table à self.tableView.contentInset = UIEdgeInsetsMake(0, 0, CGRectGetHeight(self.footerView), 0); et configurez les méthodes suivantes:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
  [self updateFooterView];
}

- (void)updateFooterView
{
  CGRect sectionFrame = [self.tableView rectForSection:0];
  CGFloat bottomSpace = self.tableView.contentOffset.y + CGRectGetHeight(self.tableView.frame) - CGRectGetMaxY(sectionFrame);
  CGFloat footerHeight = CGRectGetHeight(self.footerView.frame);
  CGFloat transformY = self.tableView.contentOffset.y + footerHeight - MIN(bottomSpace,footerHeight);

  CGRect footerFrame = self.footerView.frame;
  footerFrame.Origin.y = self.tableView.bounds.size.height - footerFrame.size.height + transformY;
  self.footerView.frame = footerFrame;
}

Chaque fois que vous devez mettre à jour le pied de page (c'est-à-dire après avoir ajouté une nouvelle ligne), appelez simplement -updateFooterView Et vous devriez être bon

0
Lucas Chwe

Vous pouvez l'utiliser pour réduire la taille du tableau en fonction du nombre de lignes dont vous disposez:

    let tblView =  UIView(frame: CGRectZero)
    tableView.tableFooterView = tblView
    tableView.tableFooterView!.hidden = true
    tableView.backgroundColor = UIColor.clearColor()

Une autre alternative serait de simplement changer la hauteur de la ligne au chemin d'index en fonction du nombre minimum de lignes que vous rencontrez ce problème.

0
Alex Zanfir