I use cell.contentView.bounds.size.width
to calculate the position of a text field in a UITableView cell. When the cell is created, debug code reports the width as 302. When the cell scrolls off the screen and then back on, the debug code reports that the it is 280--every time. It doesn't seem to want to go back to 302 and stays stuck at 280. The net result is that the text field gets put in the wrong place the second time the field is put into the cell's contentView, though it was put in the right place the first time.
I figure 22 is significant somehow, but I don't know what it is. Guessing it might be the disclosure arrow, I moved the "clear the cell" code up front of the width determination, including setting the accessory to nada.
Can anybody tell me what's going on here?
The code (with irrelevant--that I know of--stuff snipped out) looks like this:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
while( [cell.contentView.subviews count] ){
id subview = [cell.contentView.subviews objectAtIndex:0];
[subview removeFromSuperview];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
8< snip!
CGFloat theCellWidth = cell.contentView.bounds.size.width - 44.0;
CGFloat theLineHeight = [[UIFont boldSystemFontOfSize: [UIFont labelFontSize]+1.0] lineHeight];
NSLog(@"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);
if (0==section) {
switch (row) {
case 2:
while( [cell.contentView.subviews count] ){
id subview = [cell.contentView.subviews objectAtIndex:0];
[subview removeFromSuperview];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = @" ";
cell.detailTextLabel.text = @"The Age";
theAgeTextField.frame = CGRectMake(10.0, 2.0, theCellWidth, theLineHeight);
// NSLog(@"cell.contentView %@",cell.contentView);
theAgeTextField.text = theAge;
theAgeTextField.font = [UIFont boldSystemFontOfSize: [UIFont labelFontSize]+1.0];
theAgeTextField.keyboardType = UIKeyboardTypeDecimalPad;
theAgeTextField.borderStyle = UITextBorderStyleNone;
theAgeTextField.userIntera开发者_C百科ctionEnabled = NO;
[cell.contentView addSubview:theAgeTextField];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
8< snip! (lots of closing braces and other stuff omitted)
return cell;
}
Want to try this one at home, boys and girls?
Start with a new Navigation-based Application. Put the following code into RootViewController.m:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(@"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);
// Configure the cell.
return cell;
}
There are only two changes in the default code required to make this happen: changing the number of rows in the section ("return 5") and the style of the cell must be UITableViewCellStyleSubtitle. Then, when you run the program, you'll see five lines of this:
2011-06-18 11:10:19.976 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.978 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.979 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.980 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.982 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
Drag some cells off the screen (drag up--down doesn't do anything) and when they reappear, you get this:
2011-06-18 11:10:24.013 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
2011-06-18 11:10:24.047 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
2011-06-18 11:10:24.130 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
Frankly, I'm frustrated as heck with this, and am so very tempted to pony up the $99 (without a working app, even) so I can have somebody at Apple weigh in on this one.
Anybody got any ideas what's going on here?
Thanks!
Wanna' see something more interesting? Try this in place of the static NSString...
line:
NSString *CellIdentifier = [NSString stringWithFormat: @"%d", arc4random() ];
NSLog(@"%@",CellIdentifier);
Now, every time, the width in the log is always 302. It would seem, then, that a reused cell has different content width than the original cell.
Again... wondering... anybody got a clue?
I suspect that what you are seeing is due to changing the cell's accessory view which will eventually resize the content view the next time the cell performs -layoutSubviews
. That should occur when the cell is added to the table but until then the bounds of the content view will not be updated.
Regardless I don't see why this would be an issue. You appear to only be concerned with setting the width of your theAgeTextField
so if you size it appropriately relative to the content view's current width and set its autoresizingMask
flags to give it a flexible width then it should grow or shrink as needed when the bounds of the content view change.
If you need more detailed layout behavior then this should probably all occur within a UITableViewCell
subclass. See -prepareForReuse
and -layoutSubviews
for opportunities to customize the cell and its subviews. Your datasource should be able to just pass theAge
to an instance of your cell subclass and not be concerned with the details of how that will be displayed.
I ran into the same thing except that the offset was 20 instead of 22. I think Jonah's answer is on the right track, but for a quick workaround that avoids the resizing behavior of cell.contentView.frame/bounds I simply used cell.frame/bounds as my reference for laying out the views within the cell's contentView.
You must implement height for row delegate method and do all your calculations in there
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// do math
return newheight;
}
It will give you what you are after, you also have access to the index path, so you can easily find the row in your array and do everything you need, otherwise you will get the size of a reused row from the queue, which is always your default row size.
精彩评论