Voici une image qui explique tout ce que je veux faire:
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.
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.
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.