web-dev-qa-db-fra.com

Comment ajouter une image avec un effet de parallaxe au-dessus de l'en-tête UITableView et garder l'en-tête collant?

Voici une image qui explique tout ce que je veux faire:

enter image description here

Ma question est la suivante: comment structurer ma vue? L'en-tête de la vue table doit être placé en haut de la table. Mais qu'en est-il de l'image la plus en haut située au-dessus de l'en-tête de la vue tableau? Dois-je ajouter la vue tabulaire dans UIScrollView?

L'effet de parallaxe peut être fait avec CATransform3D, mais comment pourrais-je atteindre ce que je veux, c'est ma question. Il y a beaucoup de démos mais je veux que ce soit fait sur mesure.

12
NSPratik

Vous pouvez ajouter une image à la vue comme - 

let imageView = UIImageView()
let lblName = UILabel()

imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300)
imageView.image = UIImage.init(named: "poster")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)

lblName.frame = CGRect(x: 20, y: 100, width: 200, height: 22)
lblName.text = "Steve Jobs"
lblName.textColor = UIColor.white
lblName.font = UIFont.systemFont(ofSize: 26)
lblName.clipsToBounds = true
imageView.addSubview(lblName)

Après cela, dans la méthode délégué tableview, vous pouvez ajouter la méthode scrollviewDidScroll comme - 

let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height)
lblName.frame = CGRect(x: 20, y: height - 30, width: 200, height: 22)

J'espère que cela vous sera utile. S'il vous plait corrigez moi si je me trompe.

 enter image description here

4
JAINESH DOSHI

Je me suis demandé comment obtenir un en-tête collant de parallaxe et j'ai trouvé cet article qui fait le travail.

Le post est dans Swift 2 mais je l’ai recodé pour Swift 4.2

CustomHeaderView

import UIKit

class CustomHeaderView: UIView {

    //MARK:- Variables
    //MARK: Constants


    //MARK: Variables
    var imageView:UIImageView!
    var colorView:UIView!
    var bgColor = UIColor(red: 235/255, green: 96/255, blue: 91/255, alpha: 1)
    var titleLabel = UILabel()
    var articleIcon:UIImageView!



    //MARK:- Constructor
    init(frame:CGRect, title: String) {

        self.titleLabel.text = title.uppercased()
        super.init(frame: frame)

        setUpView()

    }

    required init?(coder aDecoder: NSCoder) {

        fatalError("init(coder:) has not been implemented")

    }



    //MARK:- Private methods
    private func setUpView() {
        backgroundColor = UIColor.white

        imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(imageView)

        colorView = UIView()
        colorView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(colorView)

        let constraints:[NSLayoutConstraint] = [
            imageView.topAnchor.constraint(equalTo: self.topAnchor),
            imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
            colorView.topAnchor.constraint(equalTo: self.topAnchor),
            colorView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            colorView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            colorView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
        ]
        NSLayoutConstraint.activate(constraints)


        imageView.image = UIImage(named: "bg-header")
        imageView.contentMode = .scaleAspectFill

        colorView.backgroundColor = bgColor
        colorView.alpha = 0.6

        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(titleLabel)
        let titlesConstraints:[NSLayoutConstraint] = [
            titleLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            titleLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 28),
            ]
        NSLayoutConstraint.activate(titlesConstraints)

        titleLabel.font = UIFont.systemFont(ofSize: 15)
        titleLabel.textAlignment = .center

        articleIcon = UIImageView()
        articleIcon.translatesAutoresizingMaskIntoConstraints = false
        addSubview(articleIcon)
        let imageConstraints:[NSLayoutConstraint] = [
            articleIcon.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            articleIcon.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 6),
            articleIcon.widthAnchor.constraint(equalToConstant: 40),
            articleIcon.heightAnchor.constraint(equalToConstant: 40)
        ]

        NSLayoutConstraint.activate(imageConstraints)
        articleIcon.image = UIImage(named: "article")
    }


    //MARK:- Public methods
    func decrementColorAlpha(offset: CGFloat) {

        if self.colorView.alpha <= 1 {

            let alphaOffset = (offset/500)/85
            self.colorView.alpha += alphaOffset

        }
    }

    func decrementArticleAlpha(offset: CGFloat) {

        if self.articleIcon.alpha >= 0 {

            let alphaOffset = max((offset - 65)/85.0, 0)
            self.articleIcon.alpha = alphaOffset

        }

    }

    func incrementColorAlpha(offset: CGFloat) {

        if self.colorView.alpha >= 0.6 {

            let alphaOffset = (offset/200)/85
            self.colorView.alpha -= alphaOffset

        }

    }

    func incrementArticleAlpha(offset: CGFloat) {

        if self.articleIcon.alpha <= 1 {

            let alphaOffset = max((offset - 65)/85, 0)
            self.articleIcon.alpha = alphaOffset

        }

    }

}

Et ensuite VieController

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    //MARK:- Variables
    //MARK: Constants


    //MARK: Variables
    var tableView:UITableView!
    var headerView:CustomHeaderView!
    var headerHeightConstraint:NSLayoutConstraint!



    //MARK: - Lifecycle methods
    override func viewDidLoad() {
        super.viewDidLoad()

        setUpHeader()
        setUpTableView()

    }



    //MARK: - Private methods
    private func setUpHeader() {

        headerView = CustomHeaderView(frame: CGRect.zero, title: "Articles")
        headerView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(headerView)

        headerHeightConstraint = headerView.heightAnchor.constraint(equalToConstant: 150)
        headerHeightConstraint.isActive = true

        let constraints:[NSLayoutConstraint] = [
            headerView.topAnchor.constraint(equalTo: view.topAnchor),
            headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ]

        NSLayoutConstraint.activate(constraints)

    }

    private func setUpTableView() {

        tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)

        let constraints:[NSLayoutConstraint] = [
            tableView.topAnchor.constraint(equalTo: headerView.bottomAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ]

        NSLayoutConstraint.activate(constraints)
        tableView.register(UITableViewCell.self,forCellReuseIdentifier: "cell")

        tableView.dataSource = self
        tableView.delegate = self

    }

    private func animateHeader() {

        self.headerHeightConstraint.constant = 150
        UIView.animate(withDuration: 0.4, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [.curveEaseInOut], animations: {
            self.view.layoutIfNeeded()
        }, completion: nil)

    }



    //MARK: - UITableView implementation
    //MARK: UITableViewDataSource implementation
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell",   for: indexPath)
        cell.textLabel?.text = "Article \(indexPath.row)"
        return cell

    }


    //MARK: UITableViewDelegate implementation
    func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if scrollView.contentOffset.y < 0 {

            self.headerHeightConstraint.constant += abs(scrollView.contentOffset.y)
            headerView.incrementColorAlpha(offset: self.headerHeightConstraint.constant)
            headerView.incrementArticleAlpha(offset: self.headerHeightConstraint.constant)

        }
        else if scrollView.contentOffset.y > 0 && self.headerHeightConstraint.constant >= 65 {

            self.headerHeightConstraint.constant -= scrollView.contentOffset.y/100
            headerView.decrementColorAlpha(offset: scrollView.contentOffset.y)
            headerView.decrementArticleAlpha(offset: self.headerHeightConstraint.constant)

            if self.headerHeightConstraint.constant < 65 {
                self.headerHeightConstraint.constant = 65
            }

        }

    }

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

        if self.headerHeightConstraint.constant > 150 {
            animateHeader()
        }

    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        if self.headerHeightConstraint.constant > 150 {
            animateHeader()
        }

    }

}

Résultat: la vidéo qui montre le lien fourni. Les prochaines étapes ajouteraient la contrainte de zone de sécurité et éventuellement un nib à l’en-tête, mais c’est à vous de décider.

1
Reimond Hill