3

I want to reuse an iPhone's UITableView on the iPad by adding a left/right margin thereby centering it. I tried using the .contentInset property, but it didn't seem to affect the right margin. Am I missing something? (I tried a negative right-inset right that didn't work either.)

(Here is a gist with test code that you can throw into a UITableViewController subclass.)

// In a UITableViewController subclass
- (void)viewDidLoad {
    [super viewDidLoad];

    // the space I want on either side of the table
    CGFloat xMargin = 100.0f;

    // increase content inset and decrease content size an equal amount
    UIEdgeInsets contentInset = self.tableView.contentInset;
    contentInset.left = xMargin;
    contentInset.right = xMargin;
    CGSize contentSize = self.tableView.contentSize;
    contentSize.width = contentSize.width -= xMargin * 2;

    self.tableView.contentSize = contentSize;
    self.tableView.contentInset = contentInset;

    // Turning autolayout off doesn't appear to help
    //self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
}

I can't just shorten the width of the table or the right margin won't have the right color or scroll the table in response to user touches.

Tables

zekel
  • 9,227
  • 10
  • 65
  • 96
  • 1
    Hmm for something like this the first thing I would try is instead of using a UITableViewController, I'd use a normal UIViewController and add the UITableView as a subview. You should easily be able to set it's frame to your liking without the background issues – rymagno Aug 01 '14 at 14:57
  • @user2608440 I tried that. (I used UITableViewController to make the example code simpler.) It's true I can easily set the frame of the tableview, but that doesn't solve my problem – the area on the sides wouldn't be part of the tableView and therefore not scrollable, as my desired screenshot implies. – zekel Aug 01 '14 at 16:31
  • 1
    Sorry for the misunderstanding. What about creating a custom UITableViewCell to achieve the look? It could still span the whole width of the screen, but each cell would have a white subview centered on it with the "margins" being either transparent or the same grey color. – rymagno Aug 01 '14 at 16:37
  • That might work. I was really hoping to avoid using a custom UITableViewCell subclass, though. (I want to use this layout throughout my app and I'd prefer to use stock UITableViewCell.) And other ideas? – zekel Aug 01 '14 at 17:35
  • The only other thing I could think of is using a gesture recognizer on the whole view to map to the tableView. But going that route seems to be more complicated for reuse across all your other views. For reuse, I personally would use normal UIViewControllers and subclass a UITableView which uses the custom cell. This way the only thing you'd need to do on each VC is add the custom UITableView as a subview and change the datasource. – rymagno Aug 01 '14 at 19:19

2 Answers2

0

If it's only centering you're worried about you can center a view inside its parent view by using:

childView.center = [parent convertPoint:parent.center fromView:parent.superview];

contentInset doesn't change the size of the view, it simply adds to the scrolling area around the content.

KerrM
  • 5,139
  • 3
  • 35
  • 60
  • I want it to have a smaller width and (still) be centered -- like having an iPhone-width table on an iPad. – zekel Jul 21 '14 at 14:43
  • In that case edit the tableView's `frame` property to change it's size and use the above line of code to center it. – KerrM Jul 21 '14 at 14:47
  • If I just shorten `tableView.frame.size.width` it will make the margin area not share the table's backgroundColor and the user won't be able to use that area to scroll. – zekel Jul 21 '14 at 14:53
  • Aha, in that case have you looked at the `contentSize` property? – KerrM Jul 21 '14 at 14:57
  • I think I should be able to reduce the contentSize.width and increase the contentInset.left/right an equivalent amount to get the effect I desire... but it doesn't seem to. – zekel Jul 21 '14 at 18:09
  • Have you got autolayout set for this view controller? – KerrM Jul 21 '14 at 18:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57699/discussion-between-zekel-and-kerrm). – zekel Jul 21 '14 at 18:17
0

One simple approach is to subclass UITableViewCell like so:

.h file:

@interface AGBTableViewCell : UITableViewCell

@property (nonatomic, assign) CGFloat minimumWidth;

@end

.m file:

@implementation AGBTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.minimumWidth = 320;
    }
    return self;
}

- (void) setFrame:(CGRect)frame {
    CGRect newFrame = frame;

    if (CGRectGetWidth(newFrame) > self.minimumWidth) {
        CGFloat margin = (CGRectGetWidth(newFrame) - self.minimumWidth) / 2;
        newFrame.origin.x = margin;
        newFrame.size.width = self.minimumWidth;
    }

    [super setFrame:newFrame];
}

@end

The cells will be inset, but you'll still be able to scroll on the sides:

enter image description here

Sample project here.

This approach will need some extra work to handle table animations like deleting rows.

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287