Reputation: 1076
I have created UITableView programmatically. I'm not using storyboards. I read and watched tons of tutorials on how to create a stretchy header but all of them use Storyboards.
As I understood, to achieve stretchy effect you have to add tableViewHeader as a subview and then move it to the back with .sendSubviewToBack and then the rest of the logic will apply.
but I can't figure out what has to be sent to subview when the header is created programmatically. When using storyboards you assign a custom header class to a variable and then add that to subview. So here's my TableViewcontroller:
import UIKit
private let reuseIdentifier = "contentCellId"
private let headerIdentifier = "headerCellId"
class ItemDetailViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
tableView.registerClass(ItemDetailsContentCell.self, forCellReuseIdentifier: reuseIdentifier)
tableView.registerClass(ItemDetailsHeaderCell.self, forHeaderFooterViewReuseIdentifier: headerIdentifier)
let headerView = tableView.tableHeaderView
print(headerView) // returns NIL
tableView.separatorStyle = .None
// TableView heights
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 500.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! ItemDetailsContentCell
// Configure the cell...
return cell
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterViewWithIdentifier(headerIdentifier)
return headerView
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
let cell = tableView.dequeueReusableHeaderFooterViewWithIdentifier(headerIdentifier) as! ItemDetailsHeaderCell
let width = view.frame.width
let imageRatio = (cell.itemImage.image?.size.height)! / (cell.itemImage.image?.size.width)!
let newHeight = width * imageRatio
return newHeight
}
// override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// return UITableViewAutomaticDimension
// }
//
// override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// return 500
// }
}
Its nothing fancy. Here's the code sample I'm trying to replicate:
@IBOutlet weak var tableView:UITableView!
@IBOutlet weak var headerView:ArticleHeaderView!
var article: Article?
// Header view configuration
private var defaultTableHeaderHeight:CGFloat = 250.0
private var lastContentOffset:CGFloat = 0.0
private let defaultHeaderImageName = "bg-pattern"
override func viewDidLoad() {
super.viewDidLoad()
tableView.separatorStyle = .None
tableView.rowHeight = UITableViewAutomaticDimension
// Add the header view to the table view background
defaultTableHeaderHeight = headerView.frame.size.height
lastContentOffset = -defaultTableHeaderHeight
print(defaultTableHeaderHeight)
print(tableView.tableHeaderView!.frame.height)
tableView.tableHeaderView = nil
tableView.addSubview(headerView)
tableView.sendSubviewToBack(headerView)
tableView.contentInset = UIEdgeInsets(top: defaultTableHeaderHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -defaultTableHeaderHeight)
// Disable content inset adjustment
self.automaticallyAdjustsScrollViewInsets = false
what's equivalent of headerView:ArticleHeaderView!
in my code?
It might sound dumb but I'm stuck. HELP!
Upvotes: 2
Views: 2532
Reputation: 1121
You could see an example here:
https://medium.com/@jeremysh/creating-a-sticky-header-for-a-uitableview-40af71653b55
The author of the article talks about how to create a Custom Header View and use it using constraints in code and applying the transformation using delegates of the scrollView which the UITableView inherits from.
He talks about both the downward and upward scrolling to make the headerView smaller or larger.
func animateHeader() {
self.headerHeightConstraint.constant = 150
UIView.animateWithDuration(0.4, delay: 0.0,
usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5,
options: .CurveEaseInOut, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if self.headerHeightConstraint.constant > 150 {
animateHeader()
}
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if self.headerHeightConstraint.constant > 150 {
animateHeader()
}
}
Upvotes: 3