Creating a Scrollable View with a Fixed Table in iOS: A Guide to Building a Custom Layout

Creating a Scrollable View with a Fixed Table in iOS

In this article, we will explore how to create a scrollable view in iOS that contains a table view. The twist is that we want the table view to display all its contents without scrolling, and the scroll view should not scroll at all. We’ll also add a button below the table view that will sit exactly below it.

Understanding the Basics

Before we dive into the code, let’s understand the basics of how views work in iOS. In iOS, views are arranged on top of each other using a concept called “layer stacking”. Each view has its own layer, which is a graphics context for drawing and layout. When multiple layers overlap, they create a visual stack.

To achieve our desired effect, we need to use two separate scroll views: one that contains the table view (and thus scrolls), and another that acts as a frame around the first scroll view. We’ll also use Auto Layout constraints to position the button below the second scroll view.

Setting Up the Storyboard

Let’s start by setting up our storyboard. Create a new single-view app in Xcode, and add a UIScrollView (with its frame set to an arbitrary value), a UITableView (also with its frame set to an arbitrary value), and a UIButton. For now, don’t worry about the buttons’ functionality - we’re just concerned with their position.

Creating the Scrollable View

In our code, we’ll create two separate scroll views. The first one will contain the table view, and will have its userInteractenable property set to false, so it won’t scroll.

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UITableView *tableView;

@end
#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the scroll view with userInteractenable = NO
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 500)];
    self.scrollView.userInteractionEnabled = NO;
    
    // Add the table view to the scroll view
    self.tableView = [[UITableView alloc] initWithFrame:self.scrollView.bounds style:UITableViewStylePlain];
    [self.scrollView addSubview:self.tableView];

    // Create a button
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitle:@"Click me" forState:UIControlStateNormal];
    [button sizeToFit]; // Set the frame to the size of the button's title
    [self.scrollView addSubview:button];

    // Add the scroll view to the main view
    [self.view addSubview:self.scrollView];
}

@end

Adding Constraints

Next, we need to add constraints to position the table view and the button within their respective scroll views.

- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the scroll view with userInteractenable = NO
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 500)];
    self.scrollView.userInteractionEnabled = NO;
    
    // Add the table view to the scroll view
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.bounds.size.width, 500) style:UITableViewStylePlain];
    [self.scrollView addSubview:self.tableView];

    // Create a button
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitle:@"Click me" forState:UIControlStateNormal];
    [button sizeToFit]; // Set the frame to the size of the button's title
    [self.scrollView addSubview:button];

    // Add constraints to position the table view and the button within their respective scroll views
    self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
    button.translatesAutoresizingMaskIntoConstraints = NO;

    [NSLayoutConstraint activateConstraints:@[
        self.tableView.topAnchor.constraint(equalTo:self.scrollView.topAnchor),
        self.tableView.leadingAnchor.constraint(equalTo:self.scrollView.leadingAnchor),
        self.tableView.trailingAnchor.constraint(equalTo:self.scrollView.trailingAnchor),

        button.topAnchor.constraint(equalTo:self.tableView.bottomAnchor, constant:20),
        button.leadingAnchor.constraint(equalTo:self.scrollView.leadingAnchor),
        button.trailingAnchor.constraint(equalTo:self scrollView.trailingAnchor),
    ]];

    // Add the scroll view to the main view
    [self.view addSubview:self.scrollView];
}

Understanding Constraints

Constraints are used in Auto Layout to define relationships between views. In our example, we’ve defined constraints that relate the UITableView and UIButton to their respective UIScrollView.

  • The UITableView’s top and leading edges are constrained to the UIScrollViews top and leading edges, respectively. This means that the table view will be positioned as far left and top of its scroll view.
  • The UIButton’s top edge is constrained to 20 points below the bottom edge of the UITableView, which is the height of our UIScrollView. Additionally, its leading and trailing edges are constrained to the same positions within their respective UIScrollView.
  • Finally, we’ve added the scroll view to the main view.

By using constraints like these, we can position the table view and button precisely where we want them.


Last modified on 2023-05-25