Text in cell truncates on rotate! (edit: also cell

2019-08-12 18:48发布

问题:

The problem:

I have a UITableViewCell which word wraps the text when it first appears, but if you rotate to landscape and back to portrait again, the text has been truncated! Why is this or how can I fix it?

Extra Detail:

My cell is of style UITableViewCellStyleSubtitle. In order to wordwrap the text (the textLabel of UITableViewCellStyleSubtitle, not the detailTextLabel), I calculate how many lines high the text is, and set this via

 cell.textLabel.numberOfLines

I cant simply set numberOfLines to 0, cos when the delete button slides in, it looks ugly. This is explained in a previous question of mine: Text stretches outside cell boundaries on delete slide

I set the height of the label via heightForRowAtIndexPath, but this is probably not the problem, because if i hard code this to a massive height, the text will still truncate after the orientation rotation.

Edit:

Since writing this I have noticed that my reuseIdentifier string wasn't the same when i tried to reuse the cell. Fixing this has improved the situation, and sometimes now the cells are fine. However, sometimes they still truncate on rotation, and also, if i scroll down and up again (so the cells are reload), they can truncate or change there height!

Code:

//This is a call back invoked by the interface when drawing the table view. This method will create a cell for each
//row and add text to each cell depending on the string retrieved from the datasource.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"SwitchCell"];
CGFloat textLabelFontSize = 19;

if (cell==nil){
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellType"] autorelease];
    // set the labels to the appropriate text for this row
    cell.textLabel.text = [(Group*)[composeData objectInChosenGroupsListAtIndex:indexPath.row]groupName];
    cell.textLabel.font = [UIFont systemFontOfSize:textLabelFontSize];

    if ([(Group*)[composeData objectInChosenGroupsListAtIndex:indexPath.row]isDynamic]){
         cell.detailTextLabel.text = NSLocalizedString(@"dynamic", @"dynamic");
    }
    else {
        //get and set the group size
        int groupSize = [(Group*)[composeData objectInChosenGroupsListAtIndex:indexPath.row]groupSize];

        if (groupSize == 1)
            cell.detailTextLabel.text = NSLocalizedString(@"1Contact", @"1 contact");
        else
            cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%dContacts", @"%d contacts"), groupSize];
    }
}

//Calculate height (so we can hard code the number of lines, which is neccesary to avoid ugly stretching when the delete button slides in)
CGFloat width = [[self table] frame].size.width-cell.indentationWidth-50;


int section = indexPath.section;

NSString *title_string = cell.textLabel.text;
NSString *detail_string = cell.detailTextLabel.text;

CGSize title_size = {0, 0};
CGSize detail_size = {0, 0};

if (title_string && [title_string isEqualToString:@""] == NO ) {
    title_size = [title_string sizeWithFont:[UIFont systemFontOfSize:textLabelFontSize]
                          constrainedToSize:CGSizeMake(width, 4000)
                              lineBreakMode:cell.textLabel.lineBreakMode];
}

if (detail_string && [title_string isEqualToString:@""] == NO ) {
    detail_size = [detail_string sizeWithFont:[UIFont systemFontOfSize:18.0]
                            constrainedToSize:CGSizeMake(width, 4000)
                                lineBreakMode:cell.detailTextLabel.lineBreakMode];
}

CGFloat title_height = title_size.height;
CGFloat detail_height = detail_size.height;

CGFloat content_size = title_height + detail_height;

CGFloat height;

switch ( section ) {

    case 0:
        height = content_size;
        break;

        //Just in case  
    default:
        height = 44.0;
        break;

}

//hard code numberOfLines, to avoid ugly stretching when delete slides in
cell.textLabel.numberOfLines = title_height/[UIFont systemFontOfSize:textLabelFontSize].lineHeight;
//set height for retrieval later if neccesary
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, height);

return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[self tableView: tableView cellForRowAtIndexPath: indexPath];
return cell.frame.size.height;
}

回答1:

This will work :

-(void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

}

-(void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}  

Now implement the following method :

-(void)checkOrientation
{
UIInterfaceOrientation orientation = self.interfaceOrientation;
if (orientation == UIDeviceOrientationLandscapeLeft||orientation==UIDeviceOrientationLandscapeRight)
{
    [tblView reloadData];  
    // Set numberOfLines = some value you think might adjust the text.
    // Set x coorinate of views if you want to change

}
else
{
    [tblView reloadData];
    // Set numberOfLines = some value you think might adjust the text.
    // Set x coordinates of views to initial x xoordinates.

}

}  

Create recievedRotate :

- (void)receivedRotate:(NSNotification *)notification
{    
[self checkOrientation];
}  

In viewDidLoad :

-(void)viewDidLoad
{  
[self checkOrientation];
}


回答2:

At this moment in time, the following code appears to work on my device, but not on the simulator. Most testing needs doing though. The key fix is in the reuse of the cell, and probably [table reloadData]

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[table reloadData];
return [super shouldAutorotateToInterfaceOrientation:YES];
}

- (void)viewDidAppear:(BOOL)animated{
[table reloadData];
[super viewDidAppear:animated];
}

//This is a call back invoked by the interface when drawing the table view. This method will create a cell for each
//row and add text to each cell depending on the string retrieved from the datasource.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSString * identifier = [NSString stringWithFormat:@"SwitchCell %d", indexPath.row]; // The cell row

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
CGFloat textLabelFontSize = 19;

if (cell==nil){
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
    // set the labels to the appropriate text for this row
    cell.textLabel.text = [(Group*)[composeData objectInChosenGroupsListAtIndex:indexPath.row]groupName];
    cell.textLabel.font = [UIFont systemFontOfSize:textLabelFontSize];

    if ([(Group*)[composeData objectInChosenGroupsListAtIndex:indexPath.row]isDynamic]){
         cell.detailTextLabel.text = NSLocalizedString(@"dynamic", @"dynamic");
    }
    else {
        //get and set the group size
        int groupSize = [(Group*)[composeData objectInChosenGroupsListAtIndex:indexPath.row]groupSize];

        if (groupSize == 1)
            cell.detailTextLabel.text = NSLocalizedString(@"1Contact", @"1 contact");
        else
            cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%dContacts", @"%d contacts"), groupSize];
    }
}


CGFloat width = [[self table] frame].size.width-cell.indentationWidth-50;

int section = indexPath.section;

NSString *title_string = cell.textLabel.text;
NSString *detail_string = cell.detailTextLabel.text;

CGSize title_size = {0, 0};
CGSize detail_size = {0, 0};

if (title_string && [title_string isEqualToString:@""] == NO ) {
    title_size = [title_string sizeWithFont:[UIFont systemFontOfSize:textLabelFontSize]
                          constrainedToSize:CGSizeMake(width, 4000)
                              lineBreakMode:cell.textLabel.lineBreakMode];
}

if (detail_string && [title_string isEqualToString:@""] == NO ) {
    detail_size = [detail_string sizeWithFont:[UIFont systemFontOfSize:18.0]
                            constrainedToSize:CGSizeMake(width, 4000)
                                lineBreakMode:cell.detailTextLabel.lineBreakMode];
}

CGFloat title_height = title_size.height;
CGFloat detail_height = detail_size.height;

CGFloat content_size = title_height + detail_height;

CGFloat height;

switch ( section ) {

    case 0:
        height = content_size;
        break;

        //Just in case  
    default:
        height = 44.0;
        break;

}

//hard code numberOfLines, to avoid ugly stretching when delete slides in
cell.textLabel.numberOfLines = title_height/[UIFont systemFontOfSize:textLabelFontSize].lineHeight;
//set height for retrieval later if neccesary
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, height);

return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[self tableView: tableView cellForRowAtIndexPath: indexPath];
return cell.frame.size.height;
}