Cocoa iOS/Touch: Keeping a subview of the UITableViewCell contentView right-aligned - ios

Let's say I have a UITableView that
is part of an iPad app
doesn't use the whole screen
changes its width, depending on the state of the app and other views
I added an extra subview (let's say an UILabel) to the UITableView's cell's contentView. I want the UILabel's right border to be 10 pixels from the right cell border at all times.
I managed to do this for an initial drawing of the table view for any width by specifically setting the cells frame after dequeuing it which also updates the contentView's width (otherwise the cells seem to be 320 pixels wide all the time).
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID] autorelease];
CGRect oldFrame = cell.frame;
cell.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, tableview.frame.size.width, oldFrame.size.height);
/* and other stuff */
}
Question: How can I keep the subviews of the cell's contentView aligned to the cell's right border when the table view's size changes at runtime?

You could try setting your cell autoresizingMask and its autoresizesSubviews properties?
Possibly this would work:
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;
cell.contentView.autoresizesSubviews = YES;
you should also set the autoresizingMask of your UILabel, I think:
label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;
Here the docs.

Related

iOS7 tableview cell.imageview extra padding?

I have a tableview which renders perfectly in iOS 6 & has done so for years. In iO7 in the same tableview either side of the cell.imageview its adding some extra padding approx 5mm either side of each image shown below thus moving my cell.textLabel.text further to the right. How would I remove this I cant seem to find the answer anywhere to this question?
In iOS7, the UITableViewCell's predefined property imageView is indented towards right by 15pt by default.
And this has nothing to do with the following UITableViewCell properties
indentationLevel
indentationWidth
shouldIndentWhileEditing
separatorInset
Therefore creating your own custom UITableViewCell is the best way to overcome it.
According to Apple, there are 2 good ways to do it:
If you want the cell to have different content components and to have these laid out in different locations, or if you want different behavioral characteristics for the cell, you have two alternatives:
Add subviews to a cell’s content view.
Create a custom subclass of UITableViewCell.
Solution:
As you don't prefer subclassing UITableViewCell, so adding custom subviews is your choice.
Simply creates your own image view and text labels, and add them through code or through storyboard. e.g.
//caution: simplied example
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//get the cell object
static NSString *CellIdentifier = #"myCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//create your own labels and image view object, specify the frame
UILabel *mainLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 220.0, 15.0)];
[cell.contentView addSubview:mainLabel];
UILabel *secondLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 20.0, 220.0, 25.0)];
[cell.contentView addSubview:secondLabel];
UIImageView *photo = [[UIImageView alloc] initWithFrame:CGRectMake(225.0, 0.0, 80.0, 45.0)];
[cell.contentView addSubview:photo];
//assign content
mainLabel.text = #"myMainTitle";
secondLabel.text = #"mySecondaryTitle";
photo.image = [UIImage imageNamed:#"myImage.png"];
return cell;
}
Note that as the predefined UITableViewCell content properties: cell.textLabel, cell.detailTextLabel and cell.imageView are untouched so they will remind nil and will not be shown.
Reference:
A Closer Look at Table View Cells
https://developer.apple.com/Library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7-SW1
Hope this help!
I probably had the same problem, the only thing that workd for me is setting the image frame:
cell.imageView.frame = CGRectMake( 0, 0, 50, 55 );
And if you are subclassing the cell, better to do:
- (void) layoutSubviews
{
[super layoutSubviews];
self.imageView.frame = CGRectMake( 0, 0, 50, 55 );
}

How to keep the text of cell label at top when cell's height increases?

I am increasing cell's height in the method heightForRowAtIndexPath, as a result of it, the label is coming centered.
How do make sure that label is still at top with the text irrespective of the height of the row?
While allocating UITableViewCell, you need to do like this..
UITableViewCell * cell;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:string];
At the time of initialization with style: UITableViewCellStyleSubtitle will come.
Hope this will work..
You can do it in two ways.
Create a custom label and set it's frame.
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT)];
[cell.contentView addSubView:lbl];
Use a UITableViewCell subclass and override -layoutSubviews. In this method, you'll want to call [super layoutSubviews].
- (void)layoutSubviews {
[super layoutSubviews];
CGSize size = self.bounds.size;
CGRect frame = CGRectMake(0.0f, 0.0f, size.width, size.height);
self.textLabel.frame = frame;
self.textLabel.contentMode = UIViewContentModeScaleAspectFit;
}
Write Following Code:
UILabel *myLable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, width, height)];
[cell.contentView addSubView: myLable];
If Also You want myLable fram is similare to myLable.text then write..
[myLable sizeToFit];
You cannot change the position of textlabel as it is auto-adjusted.
First option is you need to subclass UITableViewCell and customize textLabel frame.
Another is that you create your own custom label and make textlabel nil. So whenever cell's height will change, your label position will not change.
Set the autolayout Top property of UILabel.
try this:
set False to "Autoresize Subviews" property of your custom cell...

Using autoResizingMask with CGRectZero

I am building a footer for a tableview's section. The height of the footer will be specified in heightForFooterInSection, so in viewForFooterInSection I would like to just add the subview and specify that the footer view should fill whatever footer height is specified (this footer size will be dynamic). So, I am using CGRectZero as the initial frame and telling the footer view to expand to fill its parent view.
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIView *footerView = [[UIView alloc] initWithFrame:CGRectZero];
footerView = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
footerView = [UIColor greenColor];
return footerView;
}
This works as expected - the footer of the table view is filled completely with the green view.
But now I want to add a UITextView to the footer. The text view should fill the same space, but leave a 5-point border:
{
UIView *footerView = [[UIView alloc] initWithFrame:CGRectZero];
footerView = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
footerView = [UIColor greenColor];
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectInset(footerView.frame, 5, 5)];
textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
textView.backgroundColor = [UIColor redColor];
[footerView addSubview:textView];
return footerView;
}
Instead of filling the footer view (with a 5 point margin), the text view does not appear at all. It likely has a frame of CGRectZero (or maybe even -5 x -5?). If I set the inset to 0, 0, however, it expands as expected.
What is the explanation for this? And If I can't use an inset of CGRectZero for the initial frame, what am I expected to use when the frame of the footerView can not be known?
CGRectInset will create a rectangle based on the existing rectangle. It doesn't refer to the footer view ever again: only when it is calculating it this one time. In this case, since you are trying to inset a rectangle with a zero size, this applies from the docs:
Discussion.
The rectangle is standardized and then the inset parameters are
applied. If the resulting rectangle would have a negative height or
width, a null rectangle is returned.
Therefore, you are creating your label with a null rectangle.
I would create the footer with a "typical" size, then an appropriately sized label with the autoResizingMask that you want, and then set your footerView to zero if that is what you want it set to.
I would guess that the TextView creates the content in the background, so at the moment of initialization it's empty. I usualy end up using [string sizeWithFont:constrainedToSize:lineBreakMode:]
CGSize size = [aString sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:CGSizeMake(320,500) lineBreakMode:NSLineBreakByWordWrapping];
CGRect frame = CGRectMake(0, 0, size.width, size.height);

iOS UITableView unexpectedly adding margins

I have a UITableView, and currently it has a single cell in it. I have written a custom TableViewCell class which inherits from UITableViewCell in order to do some custom drawing. I have set the width of the table to the desired size, and am trying to set the width of the cell to the same size, so it will fill up the entire width of the table. The problem seems to be that I'm getting some margins on the left and right sides of the cell, and I don't know why.
Here's an example of the problem.
I made the TableView background black to be more clear. The TableView is the correct size. The background image is added to the cell, not the table, and it should be taking up the full width of the table.
I have tried making the TableView wider (as wide as the screen) to try to accommodate the size of the background image, but that doesn't quite do it. I would rather just figure out where these margins are coming from, and how I can get rid of them.
The TableView itself is initialized in Interface Builder. The style is set to Grouped, scrolling is disabled, and the view mode is set to Scale To Fill.
Here's the cell class' initWithStyle method
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// Initialization code
_primaryLabel = [[UILabel alloc] init];
_primaryLabel.textAlignment = UITextAlignmentLeft;
_primaryLabel.font = [UIFont systemFontOfSize:18];
_primaryLabel.backgroundColor = [UIColor clearColor];
_detailLabel = [[UILabel alloc] init];
_detailLabel.textAlignment = UITextAlignmentLeft;
_detailLabel.font = [UIFont systemFontOfSize:12];
_detailLabel.backgroundColor = [UIColor clearColor];
_icon = [[UIImageView alloc] init];
[self.contentView addSubview:_primaryLabel];
[self.contentView addSubview:_detailLabel];
[self.contentView addSubview:_icon];
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView* whiteDisclosureView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 15, 13)];
[whiteDisclosureView setImage:[UIImage imageNamed:#"white_disclosure.png"]];
self.accessoryView = whiteDisclosureView;
UIImageView * background = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 305, 61)];
[background setImage:[UIImage imageNamed:#"button_silver.png"]];
[self setBackgroundView:background];
self.backgroundColor = [UIColor clearColor];
self.frame = self.contentView.frame = CGRectMake(0, 0, 305, 61);
}
return self;
}
Is your tableView using "grouped" style? With grouped style, iOS normally adds left and right margin for the table cells.
It may be possible to remedy this by adjusting the frame of the tableView to slightly outside its superview. See here for example in previous question
You shouldn't explicitly set your cell's frame (size), but declare its style. (If you don't do that already) The cells are designed to automatically take up the whole space. (Horizontally)
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
If not when allocating your cell, how do you set the cell's frame?
EDIT: Instead of using hardcoded frame sizes, use self.frame. Additionally, remove the last statement where you set the frame.
Another alternative solution I used.
#jonkroll's solution does work but it does not fulfil my need. I have a header section in the table view which I want to keep the margin left and right as is, but want to remove them on the normal cell.
The solution I did is to implement a layoutSubViews method in a custom table view cell. Within this method, set the contentView's width equal to table cell's width.
-(void)layoutSubviews {
self.contentView.frame.size.width = self.frame.size.width;
}
This may be very late, but I think some people will run into the same problem as well. Hope this solution works for you guys : )

Vertical space between UITableViewCells after setting the backgroundView on a cell

I am implementing UITableViewCells that have a custom background and expands when tapped.
I am setting a custom view as my UITableViewCells backgroundView: (in RowForIndexPath)
if (cell == nil) {
CGRect f = CGRectMake(0.0f, 0.0f, 300.0f, 50.0f);
cell = [[UITableViewCell alloc] initWithFrame:f reuseIdentifier:cellIdentifier];
UIView *back = [[UIView alloc] initWithFrame:CGRectMake(10.0f, 10.0f, 300.0f, 50.0f)];
back.layer.cornerRadius = 8.0f;
[back setBackgroundColor:[UIColor blackColor]];
This works fine, by setting the backgroundView instead of the contentView, my backgroundView scales to accommodate the new size of the cell after it expands (changing the height in heightForRowAtIndexPath after a tap).
My problem is now that I would like a few pixels vertical space between my cells. Using the above approach will make the rounded black cells be displayed "back to back".
Is there a way to add the vertical space between the cells or is there a completely different approach I can take to obtain the desired look of my cells?
Thanks in advance.
In order to display a space between cells and avoid the "back to back" issue that you are having you can add a UIView with the the following frame CGRectMake(0, 0, 320, 1) and the background set to a light gray for the standard cell separator or if you just want some padding you can make the background clear.
Personally I like to use interface builder but you can of course do this programmatically.
UIView *cellSeparator = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320 ,1)];
[cellSeparator setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleWidth];
[cellSeparator setContentMode:UIViewContentModeTopLeft];
[cellSeparator setBackgroundColor:[UIColor lightGrayColor]];
[cell addSubview:cellSeparator];
[cellSeparator release];
The reason I set the cellSeparator at the top of the cell is because the effect is really for the cells that fall in between the first and last rows. Also it is important to set the autoresizingMask and the contentMode to make sure the cell separator adjusts properly when you make size changes to the UITableViewCell. If you have any elements in the cell that start at x=0 y=0 of you will need to move them down the height of the cell separator plus perhaps some additional pixels for padding so that the separator doesn't run through any elements with in the cell.

Resources