0
votes

I'm doing the usual "add your own labels/images to cell.contentview" from within a controller's cellForRowAtIndexPath. And I'm trying to have one of the labels have animated scrolling text: that is, if the text in the label is overflows the viewCell width, the label in the cell should scroll the text (animated - not manual). Also, this whole tableview + scrolling text should work for both iPhone and iPad (so everything needs to autoresize accordingly).

Cutting to the chase, the question is:

How do I get a a subview of cell.contentView to update it's frame size on time for testing if the text inside this subview overflows or not.

Or perhaps, is this even the right way to go about it?

Here's an image of what I mean (secondLabel,etc are explained below):

Now you can keep reading for the details:

The way I tried going about it is having cellForRowAtIndexPath add a custom UISCrollLabelView instance to a cell's contentView. Where this custom class is really a UIView that manages internally a UILabel.

UISCrollLabelView should autoresize to it doesn't overflow the table cell (should work for both iPhone and iPad). And then, depending on the length of the text passed in to it by cellForRowAtIndexPath, it should autoresize its internal label to fit all the text and if the label ends up overflowing the view (self), animate the scrolling of the UILabel.

I have a couple problems with this, but the main one being: UIScrollableView triggers (or not) the animation based on comparing its internal label's frame.size.width with self.frame.size.width. But apparently, it takes some time for self's frame width to update from 0 to the size it ends up resizing to after inserted in the cell.contenView. Which means that when my custom UIScrollLabelView tests (label.frame.size.width > self.frame.size.width) this is always true and text that does not overflow still scrolls. A second or so later, self.frame does update to the correct size.

Here's cellForRowAtIndexPath (secondLabel is the scrollView here):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UIImageSmartView *cachedImage;
  UILabel *mainLabel;
  UIScrollLabelView *secondLabel;

  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil) 
  {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:CellIdentifier] autorelease];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.selectionStyle = UITableViewCellSelectionStyleGray;

    mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(70, 0, 0, 20)] autorelease];
    mainLabel.font = [UIFont boldSystemFontOfSize:18];
    mainLabel.textAlignment = UITextAlignmentLeft;
    mainLabel.textColor = [UIColor blackColor];
    mainLabel.backgroundColor = [UIColor clearColor];
    mainLabel.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin);
    mainLabel.tag = MAINLABEL_TAG;

    secondLabel = [[[UIScrollLabelView alloc] initWithFrame:CGRectMake(70, 40, 0, 20)] autorelease];
    secondLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin);
    //secondLabel.backgroundColor = [UIColor clearColor];
    secondLabel.tag = SECONDLABEL_TAG;

    cachedImage = [[UIImageSmartView alloc] initWithFrame:CGRectMake(5, 5, 57, 80)];
    cachedImage.tag = PHOTO_TAG;

    [cell.contentView addSubview:cachedImage];
    [cell.contentView addSubview:mainLabel];
    [cell.contentView addSubview:secondLabel];

  }
  else
  {
    cachedImage = (UIImageSmartView*)[cell.contentView viewWithTag:PHOTO_TAG];
    mainLabel = (UILabel*)[cell.contentView viewWithTag:MAINLABEL_TAG];
    secondLabel = (UIScrollLabelView*)[cell.contentView viewWithTag:SECONDLABEL_TAG]; 
  }

  // Configure the cell...

  NSString *ImageName = [[dbData objectAtIndex:indexPath.row] objectAtIndex:2];
  NSString *imageURL = [NSString stringWithFormat:@"http://someserver", referencingTable];
  [cachedImage loadAndCacheImageFromFile:ImageName fromURL:imageURL inSize:CGSizeMake(57, 80) withBorderWidth:4];

  mainLabel.text = [[dbData objectAtIndex:indexPath.row] objectAtIndex:0];

  // -> At this point I load the text into the "scrolling label" 
  //    (actually a UIView with a label)
  [secondLabel setScrollingText:[[dbData objectAtIndex:indexPath.row] objectAtIndex:1]];

  return cell;
}

And my UIScrollLabelView implementation looks like this so far:

@implementation UIScrollLabelView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // Initialization code
      isScrolling = NO;

      self.clipsToBounds = YES;
      UILabel *label = [[[UILabel alloc] init] autorelease];
      label.font = [UIFont systemFontOfSize:14.0];
      label.textAlignment = UITextAlignmentLeft;
      label.textColor = [UIColor darkGrayColor];
      label.backgroundColor = [UIColor greenColor];
      self.backgroundColor = [UIColor redColor];
      //label.backgroundColor = [UIColor clearColor];

      [self addSubview: label];

    }
    return self;
}

- (void)setScrollingText:(NSString*)text
{
  [self setNeedsLayout];
  UILabel *label = [[self subviews ] objectAtIndex:0];
  label.text = text;
  [label sizeToFit];

  if(label.frame.size.width > self.frame.size.width)
    [self scrollText];

}

- (void)scrollText
{
  if(isScrolling)
        return;

  isScrolling = YES;

  UILabel *label = [[self subviews ] objectAtIndex:0];

    [UIView beginAnimations:@"scroll" context:nil];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDidStopSelector:@selector(scrollDidComplete)];
    [UIView setAnimationDuration: label.frame.size.width/(float)100];

    CGRect frame = label.frame;
    if(frame.origin.x == 0)
      frame.origin.x = frame.origin.x - (frame.size.width - self.frame.size.width); 
    else
      frame.origin.x = 0;

    label.frame = frame;    
    [UIView commitAnimations];

}

- (void)scrollDidComplete
{
  isScrolling = NO;
  [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(scrollText) userInfo:nil repeats:NO];
} 


@end
1

1 Answers

0
votes

You are setting the label size when the size of the cell is not defined, yet. And then you never check for the actual size again. You need to override setFrame and setBounds to catch frame size changes.