I have a custom UITableViewCell that is being displayed in tableView. This UITableViewCell is generated from a nib file. The UITableViewCell has a UILabel in it.The code of this is given below.Apparently I have tried to decrease the font size to a fixed size and nothing seems to work.Here is what I am currently doing to set the font size.
In the UITableViewCell (this is the .m file attached to the nib) here is what I do
- (void)awakeFromNib
{
UIFont *myFont = [ UIFont fontWithName: #"Arial" size: 4.0 ];
self.LabelMyLabel.font = myFont;
}
This is how the TableView is being created
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *TransferIdentifier = #"TransferTableItem";
FileTransferTableCell *cell = [tableView dequeueReusableCellWithIdentifier:TransferIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"FileCustomTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//Set the text in the UITableViewCell here
cell.textLabel.text = [self.MyArray objectAtIndex:indexPath.row];
return cell;
}
I would appreciate it if anyone could help me figure out why my textsize is always constant (I have also decreased the font size of the label in UITableViewCell in interface builder) ?
The setting of the label's font is working. The problem is that you are setting the text of the wrong label. You are saying:
cell.textLabel.text = [self.MyArray objectAtIndex:indexPath.row];
That's the wrong label. You want to set the text of LabelMyLabel, not textLabel. They are two different labels.
Change cell.textLabel.text to cell.LabelMyLabel as it is setup in your nib.
Related
I'm working on an iOS project .I created an UITableView to display a list of drones . Everything works fine but I noticed that there is a bug when I click on the cell to display the details of the drone . As u can see in the images below.
When the tableView get loded
When clicked on cell
and this my code when I select a cell :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *_storyboardName = #"Main";
UIStoryboard *_storyboard = [UIStoryboard storyboardWithName:_storyboardName bundle: nil];
DroneDetailsViewController *detailsVC = [_storyboard instantiateViewControllerWithIdentifier:#"DroneDetailsViewController"];
detailsVC.droneObj = [drones objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailsVC animated:YES];
[detailsVC.navigationController setNavigationBarHidden:NO animated:YES];
}
This my code for cellForRowAtIndexPath :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"drone";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
DroneObject *droneObjDisplay = nil;
droneObjDisplay = [drones objectAtIndex:indexPath.row];
NSData *data = [[NSData alloc]initWithBase64EncodedString:droneObjDisplay.modelMSide options:NSDataBase64DecodingIgnoreUnknownCharacters];
[self initCellWithComponents:cell :data :droneObjDisplay.modelName :droneObjDisplay.modelNumber];
return cell;
}
and this the initCelWithComponents :
- (void)initCellWithComponents :(UITableViewCell *)cell :(NSData *)dataImage :(NSString *)title :(NSString *)subTitle {
UIView *viewCell = [[UIView alloc] initWithFrame:CGRectMake(VIEW_MARGIN, VIEW_MARGIN, widthtScreen-20, VIEW_IMAGE_HEIGHT)];
viewCell.layer.borderColor = [UIColor colorWithHexString:NSLocalizedString(#"border_color", nil)].CGColor;
viewCell.backgroundColor = [UIColor whiteColor];
viewCell.layer.borderWidth = 0.5f;
UIImageView *image = [[UIImageView alloc]initWithFrame:CGRectMake(VIEW_MARGIN,VIEW_MARGIN, VIEW_IMAGE_HEIGHT-(2*VIEW_MARGIN),VIEW_IMAGE_HEIGHT-(2*VIEW_MARGIN))];
image.image=[UIImage imageWithData:dataImage];
[viewCell addSubview:image];
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(image.frame.size.width+2*VIEW_MARGIN, VIEW_MARGIN, viewCell.frame.size.width-(VIEW_IMAGE_HEIGHT-(4*VIEW_MARGIN)), 21)];
titleLabel.text = title;
titleLabel.textColor = [UIColor blackColor];
[titleLabel setFont:[UIFont systemFontOfSize:15]];
[viewCell addSubview:titleLabel];
UILabel *subTitleLabel = [[UILabel alloc]initWithFrame:CGRectMake(image.frame.size.width+2*VIEW_MARGIN, 3*VIEW_MARGIN, viewCell.frame.size.width-(VIEW_IMAGE_HEIGHT-(4*VIEW_MARGIN)), 21)];
subTitleLabel.text = subTitle;
subTitleLabel.textColor = [UIColor blackColor];
[subTitleLabel setFont:[UIFont systemFontOfSize:13]];
[viewCell addSubview:subTitleLabel];
cell.contentView.backgroundColor = [UIColor colorWithHexString:NSLocalizedString(#"gray_background", nil)];
[cell.contentView addSubview:viewCell];
}
any ideas how to fix that ?!
Your cell's style is UITableViewCellStyleSubtitle and you also adding title and subtitle label manually also.
If you are using cell's style as UITableViewCellStyleSubtitle then you can directly use
cell.textLabel.text = #"your title label's text";
cell.detailTextLabel.text = #"your detail label's text";
If you will add another label then it will creates duplicate!!!!
Since you are initialising UIView and UILabel in method inside cellForRowAtIndexPath and adding them as subview, these controls are being added to your cell each time cell is reloaded. Below code identifies each cell with a unique identifier and loads the cell only if that particular cell is not available in UITableView.
I have written droneObjDisplay.droneId to uniquely identify cell, you can write anything for droneObjDisplay.__ that is unique identifier of your object.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DroneObject *droneObjDisplay = nil;
droneObjDisplay = [drones objectAtIndex:indexPath.row];
NSString *CellIdentifier = [NSString stringWithFormat:#"drone_%d", droneObjDisplay.droneId];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSData *data = [[NSData alloc]initWithBase64EncodedString:droneObjDisplay.modelMSide options:NSDataBase64DecodingIgnoreUnknownCharacters];
[self initCellWithComponents:cell :data :droneObjDisplay.modelName :droneObjDisplay.modelNumber];
}
return cell;
}
Hope it helps.
The TableViewCell could be designed and used by either one of the following ways,
If you are using the storyboard then you can simply design the prototype cell on the TableView on storyboard itself and then giving an identifier to the cell. If you are using this way then add the component on the storyboard only and give tag to each component to access it in the code if you are not subclassing the UITableViewCell, and dequeue the cell as below,
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *labelValue = (UILabel*) [cell viewWithTag:10];
Design the TableViewCell on the storyboard as you did in 1 way and then simply create a subclass of UITableViewCell class and set that class as a Custom Class of the cell by selecting the cell on storyboard, this way you can create the outlet of each component in the cell and you do not need to access the component by the tags. Below is the code to dequeue the cell,
CellSubClassed *cell = (CellSubClassed*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.labelXYZ.text = arrayDataSource[indexPath.row][#"key"];
This is the old way before storyboard was introduced, Create subclass of UITableView cell and create a xib file with the same name you give to UiTableViewCell subclass, create the outlets of component you want to access. Below is the code to dequeue cell,
NSArray *nib;
static NSString *strNibName = #"CustomCell";
nib = [[NSBundle mainBundle] loadNibNamed:strNibName owner:self options:nil];
CustomCell *cell = [nib objectAtIndex:0];
cell.imageView.image = arrayDataSource[indexPath.row];
The last way is using TableView's default cells, just create the tableView on storyboard/xib and dequeue the cell as below,
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"xyz";
The default tableView cell styles are,
UITableViewCellStyleDefault
UITableViewCellStyleSubtitle
UITableViewCellStyleValue1
UITableViewCellStyleValue2
You can read about more on Apple Developer docs here.
So in your case you are mixing the two ways of dequeuing the cell, if you want to add the component manually as you did and you don't want to design the component on the storyboard or Xib then you just create the subclass of UITableView cell and then create the component in the awakeFromNib method and dequeue the cell as explained in 3 way.
Hope it helps you.
Ok finally, after getting your answers guys , I created a Custom Cell a subclass of UITableViewCell and I added all my components there . The main problem was how I will call it without UI (storyboard or xib ) just by code .
So after the creation of the custom cell I added this line to my viewdidload :
[self.tableView registerClass:[CustomCellTableViewCell class] forCellReuseIdentifier:#"CustomCellTableViewCell"];
then in the cellForRowAtIndexPath I just added the custom cell :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DroneObject *droneObjDisplay = nil;
droneObjDisplay = [drones objectAtIndex:indexPath.row];
static NSString *identifier = #"CustomCellTableViewCell";
CustomCellTableViewCell *cell = (CustomCellTableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
NSData *data = [[NSData alloc]initWithBase64EncodedString:droneObjDisplay.modelMSide options:NSDataBase64DecodingIgnoreUnknownCharacters];
cell.image.image = [UIImage imageWithData:data];
cell.titleLabel.text = droneObjDisplay.modelName;
cell.subTitleLabel.text = droneObjDisplay.modelNumber;
return cell;
}
I'm having some troubles with auto-resizing table view cells. I've been able to resize a cell's label based on its amount of text but I'm unable to adjust the cell height accordingly. Here's some code:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
_cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (_cell == nil)
{
_cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PFObject *object = [_postsArray objectAtIndex:indexPath.row];
NSString *nameString = [object objectForKey:#"Name"];
_cell.cellLabel.text = [NSString stringWithFormat:#"Posted by %#", nameString];
_cell.cellPostLabel.text = [NSString stringWithFormat:#" %#", [object objectForKey:#"PostedDream"]];
[_cell.cellPostLabel sizeToFit];
[tableView setAutoresizesSubviews:YES];
NSLog(#"cell post label height: %f", _cell.cellPostLabel.frame.size.height);
return _cell;
}
Things to note are that I am using a custom table view cell called TableViewCell *cell subclassed from UITableViewCell and the cell and its labels were added through IB.
The label that's being adjusted is cellPostLabel and it adjusts perfectly depending on the amount of text, but it gets cut off due to the cell not adjusting as well.
I also tried calling [self.tableView setAutoresizesSubviews:YES]; and
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight; in viewDidAppear: but still nothing. Any suggestions would be appreciated.
Cell height is determined by heightForRowAtIndexPath method.
You can implement that method on your viewcontroller and return height you prefer.
If your cell should have different height you should implement that method and return different value each cells. Or not just return static value or set tableview's property rowHeight, in this case you don't need to implement that method.
I tried to use autolayout in custom uitableviewcell
And tried to implement the dynamic height according to this SO topic
Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
But my cell is created by xib file. So the method is somewhat different
Here is my code in heightForRowAtIndexPath
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
myDataItem *item= [[data items] objectAtIndex:[indexPath row]];
CustomCell *cell = [self.offscreenCells objectForKey:#"CustomCell"];
if (!cell) {
cell = [CustomCell alloc] init];
[self.offscreenCells setObject:cell forKey:#"CustomCell"];
}
[cell.commentView setText:item.comment];
[cell.displayNameView setText:item.displayNameOfItemOwner];
[cell.timeAgoView setText:item.timeAgo];
[cell.imageView setImage:[UIImage imageNamed:#"sis_profile_placeholder"]];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(_prototypeCell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height+1; }
And the height that I got from [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] is alway "nil"
"
When I tried to debug ,I found that all subviews of my customcell are "nil" but the cell itself is not "nil". This might because the customCell of mine is made by nib and when I do [[CustomCell alloc] init] the cell is not fully created.
But I did tried to change method to cell = [_tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
The result is still the same. Every subview is nil . This make the height return to be zero and the make my tableView display incorrectly. Are there any way to solve this ?
I tried to make these upon AutoLayout .Actually, in the previous version ,that I didn't use AutoLayout and calculate the cell height manually .It did work perfectly. Anyway, I just want to tried AutoLayout.
Please help .Thanks in advance
Here is my solution
I alloc new cell by
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
myDataItem *item= [[data items] objectAtIndex:[indexPath row]];
CustomCell *cell = [self.offscreenCells objectForKey:#"CustomCell"];
if (!cell) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
[self.offscreenCells setObject:cell forKey:#"CustomCell"];
}
[cell.commentView setText:item.comment];
[cell.displayNameView setText:item.displayNameOfItemOwner];
[cell.timeAgoView setText:item.timeAgo];
[cell.imageView setImage:[UIImage imageNamed:#"image"]];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(_prototypeCell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height+1; }
As far as I know, under iOS 8 the proposed solution is not going to work for cells with multiline labels because systemLayoutSizeFittingSize will not take into account the desired cell width (simply put, it will try to layout the label into a single line, thus making the cell wider than it should).
I managed to solve this issue by installing a width constraint in cell's contentView instead of setting the cell bounds. Remember to uninstall such constraint right after calling systemLayoutSizeFittingSize:.
I'm trying to have a label in a UITableViewCell that can span two lines, but if there is only one line align it vertically to the first line.
The code to work out the label height (below) seems to work, but the label isn't getting relaid/repainted. If I scroll the cell off the view and back again, the label has the correct height.
I have tried [cell setNeedsLayout], [cell setNeedsDisplay], [titleLabel setNeedsLayout] and [titleLabel setNeedsLayout, and no combination has worked.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ItemCell" forIndexPath:indexPath];
Item *item = (self.items)[indexPath.section][indexPath.row];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
titleLabel.text = item.title;
titleLabel.backgroundColor = [UIColor redColor];
// Some titles span two lines, so resize to fit the new content.
CGRect textRect = [titleLabel.attributedText boundingRectWithSize:CGSizeMake(titleLabel.frame.size.width, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];
CGRect labelRect = CGRectIntegral(CGRectMake(titleLabel.frame.origin.x,
titleLabel.frame.origin.y,
titleLabel.frame.size.width,
textRect.size.height));
NSLog(#"%#, %f", titleLabel.text, labelRect.size.height); // This logs out the correct height
titleLabel.frame = labelRect;
return cell;
}
please try my suggestion. may be it will help you with the reusability of cell in UITableview. Please Check the following points in you code:
What to do if you cell == nil while redrawing UITableView in iPhone. thats why you have to make condition like below for reusability of UITableViewCell.
// Get table View Cell
static NSString *CellIdentifier = #"ItemCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib;
nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (UITableViewCell *) [nib objectAtIndex:0];
}
Please test it and let me know.
Turns out I'm using auto layout, which means I can't set the frame directly. Instead I need to add a height constraint and connect it to an IBOutlet on my UITableViewCell subclass.
I'm using this code to resize the labels that maintains the titles of my cells. The problem is that the cells labels are not resizing until I scroll the table. Cells need to disappear to resize their labels correctly. What can I do to get all the cells labels well resized without having to scroll previously?
Thanks for reading.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ExampleTableViewCell *cell = (ExampleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"ExampleTableViewCell"];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ExampleTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.title.text = [self.test objectAtIndex:[indexPath row]];
//Calculates the expected size based on the font and linebreak mode of the label.
CGSize maximumLabelSize = CGSizeMake(200, [UIScreen mainScreen].bounds.size.width);
CGSize expectedLabelSize = [cell.title.text sizeWithFont:cell.title.font constrainedToSize:maximumLabelSize lineBreakMode:cell.title.lineBreakMode];
// Adjusts the label the the new height.
CGRect newFrame = cell.title.frame;
newFrame.size.height = expectedLabelSize.height;
cell.title.frame = newFrame;
return cell;
}
Try to write the same code in
willDisplayCell method of UItableViewController
Another approach is .... in your ExampleTableViewCell class implement
- (void)layoutSubviews{
}
set your title's frame in above function. It should work
you must implement the method heightForRowAtIndexPath and return the height of cell then your problem solved :-)
I found Matt Long's solution really helpful (http://www.cimgf.com/2009/09/23/uitableviewcell-dynamic-height/).