web-dev-qa-db-fra.com

Définition de la hauteur de l'en-tête tableView en Swift

J'essaie de définir la hauteur d'une vue qui se trouve au-dessus de ma cellule prototype dans un contrôleur de vue de table. J'utilise IB pour définir sa hauteur (inspecteur de taille) et la définir sur 61 comme ceci (la vue verte est la vue `` en-tête ''):

header view

Mais chaque fois que je lance l'application, sa hauteur finit par être 568.0. J'ai un IBOutlet appelé testUIView pour la vue dans mon contrôleur de vue de table, et je fais: println("testUIView Height->\(testUIView.frame.height)") et finit par être 568.0 Au moment de l'exécution.

Voici une capture d'écran montrant sa hauteur à l'exécution:

enter image description here

Ma question est donc la suivante: comment puis-je définir la hauteur de la vue pour qu'elle soit de 61 au moment de l'exécution afin qu'elle ressemble en effet à ma première capture d'écran (en termes de taille)?

J'ai essayé de définir sa propriété 'height dans override func viewWillLayoutSubviews() mais cela ne m'a pas permis d'attribuer une valeur à la hauteur testUIView.frame.height = CGFloat(61.0).

Toute aide est appréciée! Merci d'avance!

À votre santé!

22
idelara

Si vous souhaitez utiliser un en-tête pour UITableView à la place, vous pouvez concevoir une autre cellule prototype dans Interface Builder, créer une classe personnalisée basée sur UITableViewCell et l'affecter à la cellule prototype dans Interface Builder sur l'inspecteur de classe.

Ensuite, dans votre contrôleur, vous allez utiliser

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?

Dans cette fonction, vous allez réellement créer une cellule réutilisable à partir de votre vue de table, mais être convertie en cellule personnalisée que vous avez créée pour l'en-tête. Vous aurez accès à toutes ses propriétés comme une UITableViewCell standard, puis vous allez simplement retourner la vue de la cellule

return cell.contentView

Une autre méthode que vous allez utiliser est

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 61.0
}

Celui-là est assez explicite.

Swift 3.0.1

public override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 61.0
}
55
Fred Faust

Swift 3/Xcode 8:

Ajoutez ceci dans viewDidLoad():

let HEADER_HEIGHT = 100
tableView.tableHeaderView?.frame.size = CGSize(width: tableView.frame.width, height: CGFloat(HEADER_HEIGHT))

Prendre plaisir!

19
Nick Ivanov

Dans Swift 4.1 et Xcode 9.4.1

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
     if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad {
        return 75.0
      } else {
        return 50.0
      }
}
1
iOS

La réponse acceptée ne répond pas réellement à la question. Il propose à la place une alternative en utilisant l'en-tête SECTION. Cette question a été répondue par d'autres, mais je vais dupliquer la réponse ici avec quelques instructions supplémentaires.


Chargement de la vue

Les vues de tableau sont aussi anciennes que les iPhones et vous devez donc parfois le forcer à faire ce que vous voulez.

Nous devons d'abord charger l'en-tête et définir manuellement sa hauteur. Sinon, la vue prendra plus de hauteur que nécessaire. Nous le faisons sur le rappel viewDidLayoutSubviews:

lazy var profileHeaderView: ProfileHeaderView = {
    let headerView = ProfileHeaderView()
    return headerView
}()

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    sizeHeaderToFit()
}

private func sizeHeaderToFit() {
    profileHeaderView.setNeedsLayout()
    profileHeaderView.layoutIfNeeded()

    var frame = profileHeaderView.frame
    frame.size.height = profileHeaderView.calculateHeight()
    profileHeaderView.frame = frame

    tableView.tableHeaderView = profileHeaderView
}

Comme vous pouvez le voir, j'aime mettre mes vues dans des vars paresseux. Cela garantit qu'ils sont toujours créés, mais uniquement lorsque je commence à les utiliser.

Vous pouvez également voir que je calcule la hauteur. Dans certains cas, votre hauteur est fixe et vous pouvez donc simplement définir la hauteur du cadre sur une valeur codée en dur.


Fixez quelques priorités

Nous verrons probablement des avertissements de contrainte apparaître dans notre débogueur. Cela se produit car la vue de table force d'abord une taille 0x0 avant d'utiliser la taille que nous avons spécifiée ci-dessus. À ce moment, vos contraintes et la hauteur de la vue sont en conflit.

Pour les supprimer, nous définissons simplement les priorités des contraintes. Vous devez d'abord envelopper vos composants de vue d'en-tête dans une autre vue (je le fais généralement toujours pour les vues d'en-tête). Cela facilitera la gestion des contraintes sur votre vue d'en-tête.

Nous devons ensuite définir les priorités de contrainte inférieure à élevé:

containerView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
containerView.setContentHuggingPriority(.defaultHigh, for: .vertical)

Voici un exemple plus complet:

AVERTISSEMENT : Bien qu'il soit toujours utile comme guide pour la présentation de vos vues, n'utilisez pas ce code si vous créez vos vues à l'aide de plumes ou de storyboards.

class ProfileHeaderView: UIView {
    lazy var containerView: UIView = {
        let view = UIView()
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayout()
    }

    required init?(coder aDecoder: NSCoder) {
        // We do this because the view is not created using storyboards or nibs.
        fatalError("init(coder:) has not been implemented")
    }

    private func setupLayout() {
        self.addSubview(containerView)

        containerView.translatesAutoresizingMaskIntoConstraints = false
        containerView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        containerView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        containerView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        containerView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
        containerView.setContentHuggingPriority(.defaultHigh, for: .vertical)

        // Set the rest of your constraints against your containerView not self and add your subviews to your containerView not self
    }
}

Voici l'exemple des contraintes définies à l'aide de snap-kit:

containerView.snp.makeConstraints() { make in
    make.top.equalTo(self.snp.top)
    make.leading.equalTo(self.snp.leading)
    make.trailing.equalTo(self.snp.trailing)
    make.bottom.equalTo(self.snp.bottom).priority(.high)
}

Assurez-vous d'ajouter vos contraintes à containerView et non self et utilisez containerView pour ajouter vos sous-vues et le reste de vos contraintes.

0
Kubee