iOS Table View Cell dont draw the first element after scrolling - ios

I create a table View with a CAGradiantLayer background.
Then I created Labels in the TableViewCell and give them Tags.
Now is my problem, that the next cell after scrolling dont appear. It seems like the next cell is overdrawing or don't get the attributes from the Subclass of UITableViewCell. But the cells after that one cell appears. If I remove the bgLayer it works. I don't know why.
This is the subclass of UITableView
- (void)drawRect:(CGRect)rect
{
NSArray *count = [Elements getElements];
CGFloat height = count.count * 44;
CGRect newRect = rect;
CAGradientLayer *bgLayer = [BGLayer getGreyGradient];
newRect.size.height = height;
bgLayer.frame = newRect;
[self.layer insertSublayer:bgLayer atIndex:0];
and this from UITableViewCell
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
UIView *bg = [[UIView alloc] init];
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
if(selected)
{
bg.backgroundColor = [UIColor redColor];
[self setBackgroundView:bg];
// cell mit tags von 100 - 106
for(NSInteger i=100; i<107; i++)
{
UILabel *str = (UILabel *)[self viewWithTag:i];
str.textColor = [UIColor whiteColor];
}
}
else
{
bg.backgroundColor = [UIColor clearColor];
[self setBackgroundView:bg];
for(NSInteger i=100; i<107; i++)
{
UILabel *str = (UILabel *)[self viewWithTag:i];
str.textColor = [UIColor blackColor];
}
}
[super setSelected:selected animated:animated];
Thanks for help

Related

UITableViewCell with subviews is not working properly

I have UITableView in my iOS app and I want to add some subviews to cell. I do it by using
[cell.contentView addSubview:someView];
and it works well, but... When I scroll down, subviews are starting to hide from cells that are on top and when I scroll back to top, they wont appear again... What I'm doing wrong? Is there some solution please?
EDIT
Mainly, I'm talking about "detailtext" label, but I have those problems in more cases...
Here is whole code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
switch (indexPath.row) {
case 0:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
break;
default:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
break;
}
UIView *separatorLine = [[UIView alloc] init];
separatorLine.frame = CGRectMake(15.0f, 60 - 0.5f, cell.frame.size.width-15.0f, 0.5f);
separatorLine.tag = 4;
separatorLine.backgroundColor = [UIColor lightGrayColor];
cell.layer.masksToBounds = NO;
tableView.backgroundColor = [UIColor colorWithRed:33.0 / 255.0 green:157.0 / 255.0 blue:147.0 / 255.0 alpha:1.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIView *row2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];
UIView *profileBorder = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-50, 50, 102, 102)];
profileBorder.layer.borderColor = [UIColor whiteColor].CGColor;
profileBorder.layer.borderWidth = 5; //2
profileBorder.layer.cornerRadius = 50;
NZCircularImageView *profileImage = [[NZCircularImageView alloc] initWithFrame:CGRectMake(1,1, 100, 100)];
profileImage.image = profilePhoto;
profileImage.contentMode = UIViewContentModeScaleAspectFill;
UITapGestureRecognizer *showBigProfilePhoto = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showImage:)];
profileImage.userInteractionEnabled = YES;
[profileImage addGestureRecognizer:showBigProfilePhoto];
[profileBorder addSubview:profileImage];
UILabel *numberFeelings = [[UILabel alloc] initWithFrame:CGRectMake(10, 100-25, 100, 50)];
numberFeelings.text = [NSString stringWithFormat:#"%#\nFeelings", feelings];
numberFeelings.font = [UIFont boldSystemFontOfSize:16];
numberFeelings.textAlignment = NSTextAlignmentCenter;
numberFeelings.textColor = [UIColor whiteColor];
numberFeelings.numberOfLines = 0;
UILabel *numberFriends = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2+60, 100-25, 100, 50)];
numberFriends.text = [NSString stringWithFormat:#"%#\nFollowers", friends];
numberFriends.font = [UIFont boldSystemFontOfSize:16];
numberFriends.textColor = [UIColor whiteColor];
numberFriends.numberOfLines = 0;
numberFriends.textAlignment = NSTextAlignmentCenter;
[row2 addSubview:profileBorder];
[row2 addSubview:numberFriends];
[row2 addSubview:numberFeelings];
int rectButtons = cell.frame.size.width-246;
UIImageView *graph = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2, -20, 82, 82)];
UIImageView *badgets = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+82, -20, 82, 82)];
UIImageView *photos = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+164, -20, 82, 82)];
graph.image = [UIImage imageNamed:#"graph.jpg"];
badgets.image = [UIImage imageNamed:#"badgets.jpg"];
photos.image = [UIImage imageNamed:#"photos.jpg"];
graph.userInteractionEnabled = YES;
badgets.userInteractionEnabled = YES;
photos.userInteractionEnabled = YES;
UITapGestureRecognizer *graphTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showGraph:)];
[graph addGestureRecognizer:graphTap];
NSArray *jmenoCasti = [name componentsSeparatedByString:#" "];
krestni = [jmenoCasti objectAtIndex:0];
int indexOfPost = indexPath.row-3;
NSMutableAttributedString *str;
int countFeeling;
int countString;
int countBeforeFeeling;
if (indexPath.row >=3) {
str = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%# was %#", krestni, [naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:#"_feel"] integerValue]]]];
countFeeling = [[naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:#"_feel"] integerValue]] length];
countString = krestni.length+5+countFeeling;
countBeforeFeeling = countString-countFeeling+1;
int rangeStart = countBeforeFeeling-1;
int rangeStop = str.length-rangeStart;
NSLog(#"%i ... %i", countBeforeFeeling-1, countString-1);
[str addAttribute:NSFontAttributeName value: [UIFont fontWithName:#"Helvetica-Bold" size:16.0f] range:NSMakeRange(rangeStart, rangeStop)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:32.0 / 255.0 green:147.0 / 255.0 blue:138.0 / 255.0 alpha:1.0] range:NSMakeRange(rangeStart, rangeStop)];
}
UILabel *mainText = [[UILabel alloc] initWithFrame:CGRectMake(15, 70, cell.frame.size.width-10, 20)];
mainText.attributedText = str;
UILabel *detailText;
if (!detailText) {
detailText = [[UILabel alloc] initWithFrame:CGRectMake(15, 90, cell.frame.size.width-10, 30)];
}
detailText.textColor = [UIColor grayColor];
detailText.font = [UIFont systemFontOfSize:13];
switch (indexPath.row) {
case 0:
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.textLabel.text = name;
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont systemFontOfSize:20];
cell.backgroundColor = [UIColor clearColor];
break;
case 1:
[cell.contentView addSubview:row2];
cell.backgroundColor = [UIColor clearColor];
break;
case 2:
cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
[cell.contentView addSubview:graph];
[cell.contentView addSubview:badgets];
[cell.contentView addSubview:photos];
break;
default:
detailText.text = [[posts objectAtIndex:indexPath.row-3] objectForKey:#"_text"];
[cell.contentView addSubview:detailText];
cell.textLabel.attributedText = str;
cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
break;
}
return cell; }
This is an easy way thats works for me:
for(UIView *subview in cell.contentView.subviews)
{
if([subview isKindOfClass: [UIView class]])
{
[subview removeFromSuperview];
}
}
You can use it at the begin of
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
In your tableView:cellForRowAtIndexPath:, you hide the info when you don't want it to be shown, but you don't explicitly unhide it for cells where it should be shown.
Look at the first two lines in that method: What you are - correctly - doing is reusing your cells, so when cells are scrolled out of view, they are removed from the UITableView and put into the reuse queue. Then, when cells should become visible, the TableView gets cells from that queue - or creates new ones if none are available.
This all goes very well, but after a while, cells with hidden info buttons are put on the queue. And then, some time later, those cells are reused - and sometimes for rows in which there should be info visible.
There are two solutions to this: You could either explicitly unhide the information for those rows where you want it to be shown, or you could use two different kinds of cell, one with hidden info, and one with visible info. You then give each of those cells a different identifier, and based on what row the cells are in, set the identifier before dequeuing/creating cells.
You should create a subclass of UITableViewCell for each different cell and add all your view related code that doesn't change depending on the data into an initialization method. Then create a method in each cell called something like configureWithData and pass in the data relevant to the cell. The creation of your attributed string and modification of label frames can occur in this configuration method.
It will dramatically reduce the clutter in your UITableViewController and is much better design wise. There is no real need for your view controller to know what your table cells look like.
Here is an example of what I am talking about:
-(void)awakeFromNib
{
if( self.accessoryType == UITableViewCellAccessoryDisclosureIndicator )
{
DTCustomColoredAccessory *accessory = [DTCustomColoredAccessory accessoryWithColor:[UIColor whiteColor]];
accessory.highlightedColor = [UIColor blackColor];
self.accessoryView = accessory;
}
}
-(void)configureCellWithObject:(id)inObject
{
TableDataModel *dataObject = (TableDataModel *)inObject;
self.titleLabel.text = dataObject.titleString;
self.subtitleLabel.text = dataObject.subtitleString;
self.accessibilityIdentifier = dataObject.accessIdString;
if( dataObject.imageUrlString != nil )
{
UIImage *iconImage = [UIImage imageNamed:dataObject.imageUrlString];
if( iconImage != nil )
{
NSInteger yOffset = [StaticTools centerYOffset:self.frame.size objectFrameSize:iconImage.size];
self.iconImageView.image = iconImage;
CGRect frame = self.iconImageView.frame;
frame.origin.y = yOffset;
frame.size = iconImage.size;
[self.iconImageView setFrame:frame];
}
else
{
[self.iconImageView loadImageFromUrl:dataObject.imageUrlString];
}
}
}

Use UITableView instead of UIPickerView to set UITextField text

I would like to use a UITextField to enter text into a UITextField instead of UIPickerView using the UITextField .tag
The view is quite complex and consists of several views which I will explain.
htmlContainerScrollView, contains multiple
- axisContainerScrollView, contains multiple
- itemField
UITableView - used to pass text into itemField
So with that in mind, this is how I set up my htmlContainerScrollView. I have added comments to explaine what I am trying to achive.
- (void) displayViews {
// add scrollview, This view is ued to hold all of the axis (vertical scrolling only)
htmlContainerScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 44.0, self.view.frame.size.width, 309.0)];
//TODO: replace this array with a dynamic implementation of the axis images. Will need someone to design the images for me
imagesArray = [NSArray arrayWithObjects:[UIImage imageNamed:#"LPA.png"], [UIImage imageNamed:#"LPB.png"], [UIImage imageNamed:#"LPC.png"], [UIImage imageNamed:#"LPD.png"], [UIImage imageNamed:#"LPA.png"], [UIImage imageNamed:#"LPB.png"], [UIImage imageNamed:#"LPC.png"], [UIImage imageNamed:#"LPD.png"], [UIImage imageNamed:#"LPA.png"], [UIImage imageNamed:#"LPB.png"], [UIImage imageNamed:#"LPC.png"], [UIImage imageNamed:#"LPD.png"], [UIImage imageNamed:#"LPA.png"], [UIImage imageNamed:#"LPB.png"], [UIImage imageNamed:#"LPC.png"], [UIImage imageNamed:#"LPD.png"], [UIImage imageNamed:#"LPA.png"], [UIImage imageNamed:#"LPB.png"], [UIImage imageNamed:#"LPC.png"], [UIImage imageNamed:#"LPD.png"], [UIImage imageNamed:#"LPA.png"], [UIImage imageNamed:#"LPB.png"], [UIImage imageNamed:#"LPC.png"], [UIImage imageNamed:#"LPD.png"], nil];
// Loop creates each axis
tagNumber = 1; // init the tagNumver starting from 1
for(int i = 0; i< axisNo; i++) {
CGFloat y = i * 77; // places each axis 77pxl below the previous
int itemsForRow = [itemsArray[i] intValue]; // get the current number of items for this axis
int scrollWidth = (itemsForRow * 40)+4; // calculate scroll width using the umber of items for this axis * by the size of each item.textfield
// create axis scroll view (horizontal scrolling only)
UIScrollView *axisContainerScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, y,self.view.frame.size.width, 77.0)]; //device view width etc.
axisContainerScrollView.contentSize = CGSizeMake(scrollWidth, 77.0); // axis.view scrollable width
axisContainerScrollView.backgroundColor = [UIColor whiteColor];
[htmlContainerScrollView addSubview:axisContainerScrollView];
// make sure the view goes right to the edge of the screen.
UIView *view = [[UIView alloc] init];
view.frame = CGRectMake(0.0, 0.0, scrollWidth+10, 77.0);
//grey header for each cell, if the total number of items exceeds the width of the device view then make the header the correct size
if(scrollWidth > self.view.frame.size.width) {
topBorder = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, scrollWidth, 18.0)];
topBorder.backgroundColor = [UIColor colorWithRed:colorController.fbRed/255.0 green:colorController.fbGreen/255.0 blue:colorController.fbBlue/255.0 alpha:1.0];
} else {
topBorder = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 18.0)];
topBorder.backgroundColor = [UIColor colorWithRed:colorController.fbRed/255.0 green:colorController.fbGreen/255.0 blue:colorController.fbBlue/255.0 alpha:1.0];
}
[axisContainerScrollView addSubview:topBorder];
[axisContainerScrollView addSubview:view];
int itemsCount = [itemsArray[i] intValue];
// add axis image to each scrollview (i.e. a, b, c, d, e, f, g etc.)
UIImageView *currentAxisImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, y, 18.0, 18.0)];
currentAxisImage.image = imagesArray[i];
[htmlContainerScrollView insertSubview:currentAxisImage aboveSubview:view];
// loop creates each item for current axis
for (int i = 0; i < itemsCount; i++) {
// create header for itemField
itemHeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake((i*40)+2, 20, 40, 15)];
itemHeaderLabel.backgroundColor = [UIColor colorWithRed:colorController.grRed/255.0 green:colorController.grGreen/255.0 blue:colorController.grBlue/255.0 alpha:1.0];
[itemHeaderLabel setTextAlignment:NSTextAlignmentCenter];
itemHeaderLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
itemHeaderLabel.textColor = [UIColor whiteColor];
NSString *strFromInt = [NSString stringWithFormat:#"%d",i+1]; // start from 1 not 0
itemHeaderLabel.text = strFromInt;
[view addSubview:itemHeaderLabel];
// itemField is the UITextField I would like to add text too from UITableViewCell selections
itemField = [[UITextField alloc] initWithFrame:CGRectMake((i*40)+2, 35, 40, 40)];
itemField.delegate = self; // set delegate so you can use UITextField delegate methods
itemField.textColor = [UIColor blackColor];
[itemField setTextAlignment:NSTextAlignmentCenter];
itemField.font = [UIFont fontWithName:#"Helvetica" size:20];
itemField.backgroundColor=[UIColor whiteColor];
itemField.layer.borderColor = [[UIColor colorWithRed:colorController.grRed/255.0 green:colorController.grGreen/255.0 blue:colorController.grBlue/255.0 alpha:1.0] CGColor];
itemField.layer.borderWidth = 0.5f;
[view addSubview:itemField];
itemField.tag = tagNumber; // set tag
tagNumber ++;
[columnArrayOfTextFields addObject:itemField]; // array of items textfields.. not using this currently but might become usefull in the future. (legacey code)
}
[rowArrayOfTextFields addObject:columnArrayOfTextFields]; // array of arrays.. not using this currently but might become usefull in the future. (legacey code)
}
// exit loop, set first reasponder to the first itemField.
[itemField viewWithTag:1];
[itemField becomeFirstResponder];
// add the whole scrollview to the mainview.
htmlContainerScrollView.contentSize = CGSizeMake(self.view.frame.size.width, 77 *axisNo);
[self.view addSubview:htmlContainerScrollView];
}
So at this point I have created the view and assigned each itemField a unique tag value. Now I will show you my didSelectRowAtIndexPath which is not complete, I think this is where I should set the text using the UITextFieldDelegates but I am not sure how.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
itemField.text = selectedCell.textLabel.text; // dose not work.. dosnt call UITextfield delegates or anything
[tableView deselectRowAtIndexPath:indexPath animated:YES]; //turns the UITableViewCell button as apposed to a single press fielf
}
and finally these are my UITextFieldDelegates.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
itemField.text = textField.text;
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO; // Hide keyboard so that you can use the UITableView selections to populate the UITextfeild itemField
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField;
{
currentSelected.text = textField.text;
NSInteger nextTag = currentSelected.tag + 1;
// Set next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// probably dont need this if I am not showing the UIkeyboard
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
You should create a custom tableview cell which has a uitextfield in it. This way you can easily set its delegate to self in cellForRowAtIndexPath like this:
- (UITableViewCell *)tableView:(UITableView *)view cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCellWithTextField* cell = .. //create cell
cell.textField.delegate = self;
return cell;
}
If you don't want to put it in tableview, fix this:
[itemField viewWithTag:1];
[itemField becomeFirstResponder];
should be:
itemField = [view viewWithTag:1];
[itemField becomeFirstResponder];

Changing Only Part of a Custom UITableViewCell Selected Background Color

I have a custom cell that I am controlling the color of when it is selected, ie the example code below:
UIView *selectedBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 600)];
[selectedBackground setBackgroundColor:[UIColor selectedCellColor]];
self.selectedBackgroundView = selectedBackground;
This works, however I would only like to have part of the cell change colors when selected. My custom cell is broken down into many different subviews, and I have it sectioned out where I would be able to define the specific view that I would like to change colors for.
How can I control the selectedBackgroundView, or use a different method, to have the background color change encompass a single subview in my cell?
Ya you are in the rite way,by subclassing the UITableView cell
hear is the sample code that you may find the answer for your question :)
//in subclassed cell class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.frame = CGRectMake(0, 0, 334, 250);
UILabel *aLabel1= [[UILabel alloc]init];
UILabel *aLabel2 = [[UILabel alloc]init];
self.label1 = aLabel1;
self.label2 = aLabel2;
self.label1.text = #"Happy";
self.label2.text = #"coding";
UIImageView *bg1 = [[UIImageView alloc]init];
bg1.tag = 100;
UIImageView *bg2 = [[UIImageView alloc]init];
bg2.tag = 200;
[self addSubview:bg1]; // you must add your background views first
[self addSubview:bg2];
[self addSubview:label1];//then other views
[self addSubview:label2];
[aLabel1 release];
[aLabel2 release];
[bg1 release];
[bg2 release];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
// Configure the view for the selected state
// hear only you can manage your background views, simply i am adding 2 imageviews by setting different colors
[super setSelected:selected animated:animated];
self.backgroundColor = [UIColor greenColor];
if(selected)
{
self.label1.backgroundColor = [UIColor redColor];
self.label2.backgroundColor = [UIColor brownColor];
UIImageView *bg1 = (UIImageView *)[self viewWithTag:100];
bg1.frame = CGRectMake(0, 0,334/2, 250);
bg1.backgroundColor = [UIColor yellowColor];
}
else
{
self.label1.backgroundColor = [UIColor brownColor];
self.label2.backgroundColor = [UIColor redColor];
UIImageView *bg2 =(UIImageView *) [self viewWithTag:200];
bg2.frame = CGRectMake(35, 0, 334/2, 250);
bg2.backgroundColor = [UIColor lightGrayColor];
}
}
-(void)layoutSubviews
{
//i am setting the frame for each views that i hav added
[super layoutSubviews];
self.label1.frame = CGRectMake(10, 10, 60, 35);
self.label2.frame = CGRectMake(65, 10, 60, 35);
}
hope helps u :)
note: i am using "without ARC"

Xcode - subview not visible

I have created a UIViewController with a UIScrollView. On the scrollView I have a page control. When I was testing it I was able to scroll horizontally through four different color pages. Now I need to add the actual views I need. In a different part of the project I created a line graph using coreplot. Now I have added made a new UIview and added the code for the line graph. I am now trying to replace the first page of the scrollView with the linegraph UIView. I am getting no errors however nothing is appearing on the screen either. It is just the default background of the scrollView. The scrollView still scrolls through the other pages correctly. I added a button programatically to the UIView to see if it had something to do with coreplot but I cannot see that either. Here is some of my code. I would appreciate any advice. Thanks.
The viewDidLoad method for my main viewController:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], nil];
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
self.alertsSubView = [[AlertsView alloc] initWithFrame:frame];
[self.scrollView addSubview:_alertsSubView];
for (int i = 1; i < numberOfGraphs; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
self.alertsSubView.delegate = self;
_scrollView.delegate = (id)self;
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
}
Here is the code for the initWithFrame method from my UIView. All of the NSLog statements get run so I know everything is being called:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSLog(#"AlertsView initWithFrame");
///button for testing
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect buttonFrame = CGRectMake(0,0, frame.size.width, frame.size.height);
self.button.frame = buttonFrame;
[self.button addTarget:self
action:#selector(buttonTouched)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.button];
[self initPlot];
}
return self;
}
I am also adding the methods initPlot and ConfigureHost in case they are relevant:
-(void)initPlot {
NSLog(#"into init plot");
[self configureHost];
[self configureGraph];
[self configurePlots];
[self configureAxes];
NSLog(#"endo of init plot");
}
-(void)configureHost {
NSLog(#"into configure host");
self.hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.bounds];
self.hostView.allowPinchScaling = YES;
[self addSubview:self.hostView];
}
I finally figured this out. Thanks for your suggestion #Eric Skroch. It actually led me down the path to the right answer even though it was not the problem. Basically to fix this problem I had to move all of the logic into the view controller and change the order of alot of the code. I am posting the relevant parts of my revised view controller here in case anyone runs across anything similar.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[_alertsSubView initPlot];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], nil];
alertFrame.origin.x = self.scrollView.frame.size.width;
alertFrame.origin.y = 0;
alertFrame.size = self.scrollView.frame.size;
_panel = [[UIView alloc]initWithFrame:alertFrame];
for (int i = 1; i < numberOfGraphs; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
_scrollView.delegate = (id)self;
self.alertsSubView.delegate = self;
}
-(AlertsView *)alertsSubView
{
if(!_alertsSubView)
{
CGRect alertsViewFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
_alertsSubView = [[AlertsView alloc] initWithFrame:alertsViewFrame];
_alertsSubView.backgroundColor = [UIColor purpleColor];
[self.scrollView addSubview:self.alertsSubView];
}
return _alertsSubView;
}

UIView frame not updating size on time for creating scrolling text animation in UILabel

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
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.

Resources