Search code examples
iosswiftuitableviewuiscrollview

UITableView inside ScrollView with infinite scroll


I have a screen which consist of two elements (UIView and UITableView). When user scrolls the screen, I want UIView go out of screen (top) and UITableView start to scroll. I'm giving a fixed height for UIView and fixed height for UITableViewCells'. In addition I'm setting bottom and top anchors but UITableView doesn't show if I don't give a specific height to UITableView. If I give specific height for a UITableView, It just show some cells not all.

In addition: At first tableView is empty because Its datasource is empty. When user taps a button inside UIView, datasource fulfills and tableview refresh data.

I some posts but all of them says giving fixed height for UITableView. I don't know how to show all cells with fixed height. Eg: Dynamic height TableView in a Scroll View

Anchors:

boxView.anchor(self.view.topAnchor, left: self.view.leftAnchor, bottom: nil, right: self.view.rightAnchor, topConstant: 20, leftConstant: 10, bottomConstant: 0, rightConstant: 10, widthConstant: 0, heightConstant: 240)
sTableView.anchor(self.boxView.bottomAnchor, left: self.view.leftAnchor, bottom: self.scrollView.bottomAnchor, right: self.view.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 100)

How I declare UITableView:

let sTableView = UITableView()
var dataSource: [SupportedService]?

let scrollView = UIScrollView()

viewDidLoad(){
sTableView.delegate = self
sTableView.dataSource = self
sTableView.register(BaseCell.self, forCellReuseIdentifier:"supportedServicesCell")
sTableView.tableFooterView = UIView()
sTableView.isScrollEnabled = false
self.scrollView.addSubview(sTableView)

self.view.addSubview(scrollView)
}
@objc func buttonTapped(_ sender: UIButton){
//Do Some Network Requests Here (Data is temp)
dataSource = DATA
sTableView.reloadData()
}

TableView Functions:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if let data = dataSource{
        return data.count
    }else{
        return 0
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "supportedServicesCell", for: indexPath) as! BaseCell
    guard let data = dataSource else { return cell }
    cell.textLabel?.text = data[indexPath.row].title

    return cell
}

How I want it before scroll:

After Scroll:


Solution

  • I have seen some apps do this. But their approach is different. I will explain that approach though if it helps. Here is what they do.

    • User interaction is disabled for the tableView in the beginning.
    • Once the user swipes the screen up. The view is animated to hide itself by going out of the screen and the tableView takes up the whole screen.
    • Now user interaction is again enabled on the tableView and it functions like a normal tableView.
    • Once the user tries to scroll down even after reaching the top of the tableView, the view is animated back to the place and the parentView return to how it was originally.