Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a TableView only take up part of the screen

By default when I drag out a TableViewController in IB the tableview takes up all the screen, and there is no way to add a UIView that stays in place even when the user scrolls the tableview (If i Say add a UIView with some buttons, then when I scroll the tableview that UIView will scroll as well.)

My program uses a UITableViewController subclass to control the tableview, what´s the easiest way of having a top bar that stays static even when the user scrolls?

like image 219
Tom Lilletveit Avatar asked Aug 27 '13 18:08

Tom Lilletveit


People also ask

Why is there extra padding at the top of my UITableView?

Starting in iOS7, there is additional space at the top of my UITableView 's which have a style UITableViewStyleGrouped . The tableview starts at the first arrow, there are 35 pixels of unexplained padding, then the green header is a UIView returned by viewForHeaderInSection (where the section is 0).


3 Answers

Simple, instead of using a UITableViewController just use a UIViewController with a UITableView placed inside it. (leaving room for you to add your secondary view above or below the table) That way, you can let the view controller's view take up the entire screen, and manually define the frame of the table view within it. There will be a little bit of rearranging required but will suit your needs.

enter image description here

The only real differences you need to be aware of, is that you'll need to make your view controller conform to both the UITableViewDelegate, and UITableViewDatasource protocols, as well as declaring the outlet for the table view yourself.

@property (weak,nonatomic) IBOutlet UITableView *tableView;

It is also important to keep in mind that there a few functions that are only available on UITableViewController like clearsSelectionOnViewWillAppear, but you can always replicate them yourself.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.tableView deselectRowAtIndexPath:self.tableView.indexPathsForSelectedRows animated:YES];
}
like image 123
Mick MacCallum Avatar answered Oct 29 '22 11:10

Mick MacCallum


The approach I recommend (and I think this is the design pattern Apple encourages) is to use an embed segue to insert your table view controller into a parent controller that contains your additional views. This helps keep things modular and helps make the overall app structure easy to understand.

The basic steps are as follows:

  1. Create a parent view controller in IB and add a container view
  2. Create an embed segue by ctrl-dragging from the container view to the view controller you want to embed.
  3. Give the segue an identifier like "EmbedMyTable".
  4. In the parent controller's prepareForSegue method, check for your embed segue's identifier and do any additional wiring. The view controller and view relationships are established automatically, but you might want configure the table view controller and keep a reference to it.
like image 24
Timothy Moose Avatar answered Oct 29 '22 09:10

Timothy Moose


Programmatically, using Swift constraints. In my opinion, this solution is cleaner:

    import UIKit

    class SettingsController : UIViewController, UITableViewDelegate, UITableViewDataSource {

    let tableView : UITableView = {
        let t = UITableView()
        t.translatesAutoresizingMaskIntoConstraints = false
        return t
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // set a background color so we can easily see the table
        self.view.backgroundColor = UIColor.blue

        // add the table view to self.view
        self.view.addSubview(tableView)

        // constrain the table view to 120-pts on the top,
        //  32-pts on left, right and bottom (just to demonstrate size/position)

        tableView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 32.0).isActive = true
        tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 120.0).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -32.0).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -32.0).isActive = true

        // set delegate and datasource
        tableView.delegate = self
        tableView.dataSource = self

        // register a defalut cell
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

    // Note: because this is NOT a subclassed UITableViewController, 
    // DataSource and Delegate functions are NOT overridden

    // MARK: - Table view data source

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        cell.textLabel?.text = "\(indexPath)"

        return cell
    }

    // MARK: - Table view delegate

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // etc
    }
}
like image 41
Kirill Kudaev Avatar answered Oct 29 '22 09:10

Kirill Kudaev