I need to create a simple chat view in which i can show messages from two ends (sender and receiver) like any Message App .
What i have done till now is , created a UITableView , A UIButton and a UITextField. And on that UIButton tap , i am adding UITextField text to array , Now I need the second end also like in ours Messaging app (sender side).
Left side is receiver and Right side is sender.
My app till now looks like
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
messageLabel = nil;
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
messageLabel = [[UILabel alloc] init];
messageLabel.tag = 101;
[cell.contentView addSubview: messageLabel];
} else {
messageLabel = (UILabel*)[cell.contentView viewWithTag: 101];
} //---calculate the height for the label---
int labelHeight = [self labelHeight:[listOfMessages objectAtIndex:indexPath.row]];
labelHeight -= bubbleFragment_height;
if (labelHeight<0) labelHeight = 0;
messageLabel.frame =
CGRectMake(bubble_x + 10, bubble_y + 5,
(bubbleFragment_width * 3) - 25,
(bubbleFragment_height * 2) + labelHeight - 10);
messageLabel.font = [UIFont systemFontOfSize:15];
messageLabel.textAlignment = NSTextAlignmentCenter;
messageLabel.textColor = [UIColor darkTextColor];
messageLabel.backgroundColor = [UIColor greenColor];
messageLabel.numberOfLines = 0;
messageLabel.layer.cornerRadius = 8;
messageLabel.layer.masksToBounds = YES;
messageLabel.text = [listOfMessages objectAtIndex:indexPath.row];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
-(void) sendAction:(id) sender {
[listOfMessages addObject:field.text];
[chatTable reloadData];
field.text = #"";
[field resignFirstResponder];
}
You can take two different custom cells one for the sender and one for the receiver like this:
for Sender
for Receiver
Now, in your app, there must be login and sign-up process as it is a chat app and there will be server associated with your app to save data.
What you can do is that, when you send the message, also send the name of the receiver with it and store it in your database.
Now, in your chat view, fetch all the message data, along with the receiver names.
Fetch the userName who is currently logged in during the Login process.
You can do something like this in your cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *myArrayElement = [arr_receiverUserName objectAtIndex:indexPath.row];
//do something useful with myArrayElement
if(![myArrayElement isEqualToString:userName])
{
/// These are my messages.
//// Pop up 'mycell' here
UILabel *lbl_myText = [[UILabel alloc]initWithFrame:CGRectZero];
[lbl_myText setLineBreakMode:NSLineBreakByWordWrapping];
lbl_myText.minimumScaleFactor = FONT_SIZE;
[lbl_myText setNumberOfLines:0];
lbl_myText.textAlignment = NSTextAlignmentRight;
[lbl_myText setFont:[UIFont systemFontOfSize:FONT_SIZE]];
NSString *text = [arr_text objectAtIndex:indexPath.row];
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE]];
// Checks if text is multi-line
if (size.width > lbl_myText.bounds.size.width)
{
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
[lbl_myText setText:text];
[lbl_myText setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - cell.imgv_myImage.frame.size.width -(CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
}
else
{
lbl_myText.frame = CGRectMake(10, 0, cell.frame.size.width - cell.imgv_myImage.frame.size.width - 18,18);
lbl_myText.textAlignment = NSTextAlignmentRight;
[lbl_myText setText:text];
}
//lbl_myText.backgroundColor = [UIColor greenColor];
[cell.contentView addSubview:lbl_myText];
}
else
{
//// These are the messages sent by some one else
/// Pop up `someonecell` here
UILabel *lbl_myText = [[UILabel alloc]initWithFrame:CGRectZero];
[lbl_myText setLineBreakMode:NSLineBreakByWordWrapping];
lbl_myText.minimumScaleFactor = FONT_SIZE;
[lbl_myText setNumberOfLines:0];
lbl_myText.textAlignment = NSTextAlignmentLeft;
[lbl_myText setFont:[UIFont systemFontOfSize:FONT_SIZE]];
NSString *text = [arr_text objectAtIndex:indexPath.row];
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE]];
// Checks if text is multi-line
if (size.width > lbl_myText.bounds.size.width)
{
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
[lbl_myText setText:text];
[lbl_myText setFrame:CGRectMake(cell.imgv_someoneImage.frame.size.width+8, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - cell.imgv_someoneImage.frame.size.width -(CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
}
else
{
lbl_myText.frame = CGRectMake(10, 0, cell.frame.size.width - cell.imgv_someoneImage.frame.size.width - 18,18);
lbl_myText.textAlignment = NSTextAlignmentLeft;
[lbl_myText setText:text];
}
//lbl_myText.backgroundColor = [UIColor greenColor];
[cell.contentView addSubview:lbl_myText];
}
You can do similar things for images and audios.
For Dynamic Height Of The Cell:
To make to the height of your cell according to your UILabels, refer to Increase the main tableview row height according to the custom cell
You need to create multiple cell with different CellIdentifier For Example. Cell For sender and receiver. And you can subdivide it in categories like text,audio,video,image.
Download sample ChatUI Demo (Objective-C & Swift) from here
Lets have example for the text chat.
First of all you need to create 2 cell prototypes in your Storyboard or XIB with different CellIdentifier for example "cellSender" and "cellReceiver".
Take UILabel or UITextView inside cell and for cellSender make left alignment and for cellReceiver make the alignment right for making different layout for sender and receiver.
Then You can do with following with your code...
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL sender = NO;
// Check for the sender or receiver
<code for checking message is from sender or receiver>
static NSString *CellIdentifier = sender?#"cellSender":#"cellReceiver";
messageLabel = nil;
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
messageLabel = [[UILabel alloc] init];
messageLabel.tag = 101;
[cell.contentView addSubview: messageLabel];
} else {
messageLabel = (UILabel*)[cell.contentView viewWithTag: 101];
} //---calculate the height for the label---
int labelHeight = [self labelHeight:[listOfMessages objectAtIndex:indexPath.row]];
labelHeight -= bubbleFragment_height;
if (labelHeight<0) labelHeight = 0;
messageLabel.frame =
CGRectMake(bubble_x + 10, bubble_y + 5,
(bubbleFragment_width * 3) - 25,
(bubbleFragment_height * 2) + labelHeight - 10);
messageLabel.font = [UIFont systemFontOfSize:15];
messageLabel.textAlignment = NSTextAlignmentLeft;
messageLabel.textColor = [UIColor darkTextColor];
messageLabel.backgroundColor = sender? [UIColor greenColor]: [UIColor lightGrayColor];
messageLabel.numberOfLines = 0;
messageLabel.layer.cornerRadius = 8;
messageLabel.layer.masksToBounds = YES;
messageLabel.text = [listOfMessages objectAtIndex:indexPath.row];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
EDIT
Related
I found a lot of answer for this question but I don't anderstand how to manage my code.
When I scroll the tableView content, the cell disappear. I just have two texts in the cell question and answer.
I've tried to use an identifier (reusable) but the code doesn't change anything...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UILabel *textLabel = nil;
NSString* text = #"";
//static NSString *CellIdentifier = #"Cell";
NSString *CellIdentifier = [NSString stringWithFormat:#"%ld_%ld",(long)indexPath.section,(long)indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
int y = -20;
float titleFontSize = 14.0f;
if(indexPath.row == 0) {
y = 0;
titleFontSize = 16.0f;
}
if(cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[textLabel setLineBreakMode:NSLineBreakByWordWrapping];
[textLabel setMinimumFontSize:14.0f];
[textLabel setNumberOfLines:0];
[textLabel setFont:[UIFont systemFontOfSize:14.0f]];
[textLabel setTag:1];
[textLabel setTextColor:[UIColor colorWithRed:57/255.0 green:55/255.0 blue:64/255.0 alpha:1.0]];
// Titre
if(indexPath.row == 0) {
text = question;
[cell setBackgroundColor:[UIColor colorWithRed:220/255.0 green:224/255.0 blue:241/255.0 alpha:1.0]];//[UIColor colorWithRed:.945f green:.921f blue:.78f alpha:1]];
[textLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:titleFontSize]];
}
// Contenu
else {
text = answer;
}
CGSize constraint = CGSizeMake(285, 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:titleFontSize] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
[textLabel setText:text];
[textLabel setFrame:CGRectMake(25, y, 275, MAX(size.height + 60, 44.0f))];
[textLabel setBackgroundColor:[UIColor clearColor]];
[cell addSubview:textLabel];
return cell;
}
UPDATE CALCULATING CELL SIZE
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
float titleFontSize = 14.0f;
float offSet = 0;
NSString *text = #"";
if(indexPath.row == 0) {
text = question;
titleFontSize = 16.f;
offSet = 10;
}
else
text = answer;
CGSize constraint = CGSizeMake(285, 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:titleFontSize] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
CGFloat height = MAX(size.height + 40, 44.0f);
return height + offSet;
}
I've had this problem in the past and it's always due to the cells height being incorrect... You've got quite a few instances where your two cells are not the same, so we are going to have to get a grip on that code.
int y
this value is also concerning me a little as it looks like it sets the textLabel frame origin.y to -20 ... if you want a different offset for Y in each cell but the rest of the cell is the same, that's fine, but in this case I think I'd suggest a different UITableViewCell subclass for the two types of cell... And change all the label properties etc inside that subclass..
So...
Make a UITableViewCell subclass for each type of cell, call them whatever you like... for example MYQuestionTableViewCell and MYAnswerTableViewCell
inside the cell MYQuestionTableViewCell .h file
#define TEXT_LABEL_WIDTH 285.0f
#define TEXT_LABEL_QUESTION_FONT_SIZE 16.0f
inside that cell MYQuestionTableViewCell .m file do
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.backgroundColor = [UIColor redColor];
self.clipsToBounds = YES; // just to make sure we're calculating the height correctly
// set up your textLabel etc. in here
self.textLabel.textColor = [UIColor whiteColor];
self.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size: TEXT_LABEL_QUESTION_FONT_SIZE]];
}
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
self.textLabel.frame = CGRectMake(0.0f, 0.0f, TEXT_LABEL_WIDTH, self.contentView.frame.size.height);
}
Now our textLabel will be whatever the height of the cell is... Now it's set in only one place, we know where the issue will be if it's not correct.
In your second MYAnswerTableViewCell subclass you'll need the other values set
.h
#define TEXT_LABEL_ANSWER_FONT_SIZE 14.0f
.m
same as the other cell but changing for it's property values
As you are also using different fonts in the two different cells... it might be easier to use a switch.. but I'll try to keep it similar to what you were doing before.. this sort of doubling up of code is the cause of the confusion, but sometimes it's unavoidable.. We'll just try to keep it as simple as we can.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat offSet = 0.0;
NSString *text = #"";
UIFont *fontUsed = nil;
if(indexPath.row == 0) {
fontUsed = [textLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size: TEXT_LABEL_QUESTION_FONT_SIZE]];
text = question;
offSet = 10.0f;
}
else
{
fontUsed =[UIFont systemFontOfSize:TEXT_LABEL_ANSWER_FONT_SIZE];
text = answer;
}
NSLog (#"TEXT: %#",text); // checking if the text is set...
CGSize constraint = CGSizeMake(TEXT_LABEL_WIDTH, HUGE_VALF); // personally I prefer HUGE_VALF for that
CGSize size = [text sizeWithFont:fontUsed constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
CGFloat height = MAX(size.height + 40.0f, 44.0f); // 40.0f for padding?
return height + offSet;
}
You shouldn't be adding labels to a cell unless you need to, they come with some provided... now your cellForRow can look like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *QuestionCellIdentifier = #"QuestionCell";
static NSString *AnswerCellIdentifier = #"AnswerCell";
if (indexPath.row == 0)
{
MYQuestionTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:QuestionCellIdentifier];
if (!cell)
cell = [[MYQuestionTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:QuestionCellIdentifier];
cell.textLabel.text = question;
return cell;
}
MYAnswerTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: AnswerCellIdentifier];
if (!cell)
cell = [[MYAnswerTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AnswerCellIdentifier];
cell.textLabel.text = answer;
return cell;
}
You'll also need
#import "MYQuestionTableViewCell.h"
#import "MYAnswerTableViewCell.h"
at the top of your view controller
i want to one size UIimageview for all cell , but
when the high size of cell is change the image is changed i want to one size of UIimage
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(!cell){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.imageView.image = [UIImage imageNamed:#"England.png"];
cell.imageView.frame = CGRectMake( 2, 0, 25, 25 );
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
UIFont * myfont = [UIFont fontWithName:#"Helvetica" size:13.0];
cell.textLabel.text = [_data objectAtIndex:indexPath.row];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.textAlignment = UITextAlignmentCenter;
cell.textLabel.font = myfont;
cell.textLabel.textColor = [UIColor grayColor];
return cell;
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * description = [_data objectAtIndex:indexPath.row];
CGSize size = [description sizeWithFont:[UIFont boldSystemFontOfSize:14.0f] constrainedToSize:CGSizeMake(190,40) lineBreakMode:UILineBreakModeWordWrap];
return size.height+50;
}
Here are the codes
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN * 5);
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UILabel *label = nil;
cell = [tv dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"Cell"] autorelease];
label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setLineBreakMode:UILineBreakModeWordWrap];
[label setMinimumFontSize:FONT_SIZE];
[label setNumberOfLines:0];
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
[label setTag:1];
[[cell contentView] addSubview:label];
}
NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
if (!label)
label = (UILabel*)[cell viewWithTag:1];
[label setText:text];
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN-10, CELL_CONTENT_MARGIN+30, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(128,5, 32, 32)];
imv.image=[UIImage imageNamed:#"England.png"];
[cell.contentView addSubview:imv];
[imv release];
return cell;
}
I have created an app with a table view. Which uses a view and a label in each cell. But if I create the views and cells in the (!cell) code it returns empty cells and if I remove the (!cell) condition it displays the data but does not take dynamic height. Can anyone please help me.
- (void)viewDidLoad{
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist", LanguageFile]];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithContentsOfFile:DataPath];
self.reloadArray = [tempDict objectForKey:#"Rows"];}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.reloadArray count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Get data for the current row
NSString *textData = [reloadArray objectAtIndex:indexPath.section]
CGFloat dataTextHeight = [self getLabelHeightForIndex:textData];
if(dataTextHeight < 44)
{
dataTextHeight = 44;
}
return dataTextHeight;
}
-(CGFloat)getLabelHeightForIndex:(NSString *)string
{
CGSize maximumSize = CGSizeMake(280, 10000);
CGSize labelHeightSize = [string sizeWithFont:[UIFont fontWithName:#"Helvetica" size:14.0f] constrainedToSize:maximumSize lineBreakMode:NSLineBreakByWordWrapping];
if(labelHeightSize.height < 44){
labelHeightSize.height = 44;
}
return labelHeightSize.height;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
static const int textViewTag = 1, textLabelTag = 2;
UIImageView *img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"standard_back.png"]];
img.frame = tableView.frame;
tableView.backgroundView = img;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// First view
UIView *textView = [[UIView alloc] initWithFrame: CGRectMake(0.0, 0.0, 280.0, 36.00)];
textView.tag = textViewTag;
textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[cell.contentView addSubview:textView];
// First label
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0, 270.0, 36.00)];
textLabel.tag = textLabelTag;
textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14.0f];
textLabel.textColor = [UIColor whiteColor];
textLabel.backgroundColor = [UIColor clearColor];
textLabel.numberOfLines = 0;
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
// textLabel.clipsToBounds = YES;
[cell.contentView addSubview:textLabel];
}
NSString *textData = [reloadArray objectAtIndex:(indexPath.section)];
CGFloat dataTextHeight = [self getLabelHeightForIndex:textData];
UIView *textView = [cell.contentView viewWithTag:textViewTag];
CGRect textViewFrame = textView.frame;
textView.frame = CGRectMake(0.0, 0.0, textViewFrame.size.width, dataTextHeight);
UILabel *textLabel = [cell.contentView viewWithTag:textLabelTag];
CGRect textLabelFrame = textLabel.frame;
textLabel.frame = CGRectMake(10.0, 0.0, textLabelFrame.size.width, dataTextHeight);
textLabel.text = textData;
textLabel.backgroundColor= [UIColor clearColor];
textLabel.textAlignment = NSTextAlignmentCenter;
cell.backgroundColor = [UIColor colorWithWhite:0 alpha:.65];
cell.textLabel.numberOfLines = 0; // Multiline
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.textLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return cell;
}
Thanks in advance.
I saw a lot of solutions but all was wrong or uncomplet.
You can solve all problems with 5 lines in viewDidLoad and autolayout.
This for objetive C:
_tableView.delegate = self;
_tableView.dataSource = self;
self.tableView.estimatedRowHeight = 80;//the estimatedRowHeight but if is more this autoincremented with autolayout
self.tableView.rowHeight = UITableViewAutomaticDimension;
[self.tableView setNeedsLayout];
[self.tableView layoutIfNeeded];
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0) ;
For swift 2.0:
self.tableView.estimatedRowHeight = 80
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)
Now create your cell with xib or into tableview in your Storyboard
With this you no need implement nothing more or override. (Don forget number os lines 0) and the bottom label (constrain) downgrade "Content Hugging Priority -- Vertical to 250"
You can donwload the code in the next url:
https://github.com/jposes22/exampleTableCellCustomHeight
References: http://candycode.io/automatically-resizing-uitableviewcells-with-dynamic-text-height-using-auto-layout/
This is a part of my code which i used in my app. It works for me fine.Ping me if u need help.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
CGSize constraintSize = {230.0, 20000}; //230 is cell width & 20000 is max height for cell
CGSize neededSize = [ [NSString stringWithFormat:#"%#",[cellar objectAtIndex:indexPath.row]] sizeWithFont:[UIFont fontWithName:#"HelveticaNeue-Medium" size:15.0f] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeCharacterWrap];
return MAX(45, neededSize.height +33);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
{ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
CGSize constraintSize = {230.0, 20000};
UILabel* label = [[UILabel alloc] init];
[label setNumberOfLines:0];
label.backgroundColor = [UIColor clearColor];
[label setFont:[UIFont fontWithName:#"HelveticaNeue-Medium" size:15.0f]];
label.adjustsFontSizeToFitWidth = NO;
CGSize neededSize = [ [NSString stringWithFormat:#"%#",[cellar objectAtIndex:indexPath.row] ] sizeWithFont:[UIFont fontWithName:#"HelveticaNeue-Medium" size:15.0f] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeCharacterWrap];
// NSLog(#"Height%f",neededSize.height);
//NSLog(#"width%f",neededSize.width);
[label setText:[NSString stringWithFormat:#"%#",[cellar objectAtIndex:indexPath.row] ]];
[label setFrame:CGRectMake(10, 2, 230, MAX(neededSize.height+30, 44.0f))];
[[cell contentView] addSubview:label];
cell.selectionStyle=UITableViewCellSelectionStyleNone;
return cell;
}
Hope it helps.!!!
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return "your content height";
}
I am creating UITableView, where each cell size will b calculated based on the text I input.
I am Calculating size of Cell in heighForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSString *text = [tableData objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(210.0f, 20000.0f);
size = [text sizeWithFont:[UIFont systemFontOfSize:12.0f] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
height = MAX(size.height, 44.0f);
return height + (CCM * 2);
}
this is how I am calculating height for each cell, now my question is - I want to add image to each cell like comment box? like this
Click here to see comment boxes I am looking for
You can see these kind of comment boxes
what I did is I made my image into two parts
first one has top part which is working well on every cell starting image is coming
now while fixing bottom part me facing problem
for small text in cell UILable its working well
when size of text in UILabel increased it's not getting properly adjusted
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = #"cell";
NSLog(#"index path %d", indexPath.row);
MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[[MyTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[cell.cellBackgroundBottom setFrame:CGRectMake(75.0f, 92.0f, 228.0f, height + 25.0f)];
[cell.cellContent setText:(NSString*)[tableData objectAtIndex:[indexPath row]]];
[cell.cellContent sizeToFit];
CGRect theFrame = [cell.cellContent frame];
theFrame.size.width = 210.0f;
[cell.cellContent setFrame: theFrame];
return cell;
}
I have created one UITableView subclass naming MYTableCell where I have defined what all I need inside my each cell.
// Creating UILabel for cell content or comments block
cellContent = [[UILabel alloc]initWithFrame: CGRectMake( 90.0f, 15.0f, 210.0f, 60.0f)] ;
[cellContent setLineBreakMode:UILineBreakModeWordWrap];
cellContent.numberOfLines = 0;
[cellContent setMinimumFontSize:15.0f];
[cellContent setBackgroundColor:[UIColor clearColor]];
// [cellContent setTextColor:[UIColor colorWithRed:73.0f green:73.0f blue:73.0f alpha:1.0f]];
[cellContent setFont:[UIFont fontWithName:#"Helvetica" size:12.0f]];
cellContent.textAlignment = UITextAlignmentLeft;
[cellContent setTag:1];
[self addSubview:cellContent];
[cellContent release];
cellBackgroundTop = [[UIImageView alloc] initWithFrame:CGRectMake(60.0f, 5.0f, 243.0f, 13.5f)];
[cellBackgroundTop setImage:[UIImage imageNamed:#"comments.png"]];
[self addSubview:cellBackgroundTop];
[cellBackgroundTop release];
cellBackgroundBottom = [[UIImageView alloc] initWithFrame:CGRectZero];
[cellBackgroundBottom setImage:[UIImage imageNamed:#"Untitled-1_09.png"]];
[self addSubview:cellBackgroundBottom];
[cellBackgroundBottom release];
I got answer for my question
. This is what i have to do in my cellForRowAtIndexPath
NSString *text = [tableData objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(210.0f, 20000.0f);
CGSize size1 = [text sizeWithFont:[UIFont systemFontOfSize:12.0f] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height1 = MAX(size1.height, 44.0f);
[cell.cellBackgroundBottom setFrame:CGRectMake(75.0f, 18.0f, 228.0f, height1 + 10.0f)];
i've implemented, in my iOS ap, some TdBadgedCell (from https://github.com/tmdvs/TDBadgedCell) in a UITabView. But when I want to manage the cells' hight dynamically by using something like this example:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN * 2);
}
the cell's width is the entire width of the cell (calculated variable "constraint" in the example below) and not the real width of the label printed on screen taking consideration of the badge's width. So, the portion of text at the end of the UILabel doesn't appear in cell when the text in too long.
How can I resolve this please?
I've solved my own problem with this portions of code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
MyObject *obj = [self.myObjects objectAtIndex:indexPath.row];
NSString *textlabel = [self getMainTextStringFromMyObject:obj];
NSString *detailtextlabel = [self getDetailTextStringFromMyObject:obj];
CGFloat height = MAX(CELL_TEXTLABEL_HEIGHT + [self getDetailTextSizeForString:detailtextlabel].height, CELL_ROW_DEFAULTHEIGHT);
return height;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MyObject *obj = [self.myObjects objectAtIndex:indexPath.row];
NSString *textlabel = [self getMainTextStringFromMyObject:obj];
NSString *detailtextlabel = [self getDetailTextStringFromMyObject:obj];
static NSString *CellIdentifier = #"ImageOnRightCell";
UILabel *mainLabel, *secondLabel;
UIImageView *photo;
TDBadgedCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[TDBadgedCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(CELL_LABELS_MARGIN, 1.0, CELL_TEXTLABEL_WIDTH, CELL_TEXTLABEL_HEIGHT)] autorelease];
mainLabel.tag = MAINLABEL_TAG;
mainLabel.font = [UIFont boldSystemFontOfSize:CELL_TEXTLABEL_FONTSIZE];
mainLabel.textColor = [UIColor blackColor];
[cell.contentView addSubview:mainLabel];
secondLabel = [[[UILabel alloc] initWithFrame:CGRectMake(CELL_LABELS_MARGIN, CELL_TEXTLABEL_HEIGHT, CELL_TEXTLABEL_WIDTH, 19.0)] autorelease];
secondLabel.tag = SECONDLABEL_TAG;
secondLabel.font = [UIFont systemFontOfSize:CELL_DETAILTEXTLABEL_FONTSIZE];
secondLabel.textColor = [UIColor darkGrayColor];
secondLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
secondLabel.numberOfLines = 0;
secondLabel.lineBreakMode = UILineBreakModeWordWrap;
[cell.contentView addSubview:secondLabel];
float yOriginImg = (cell.contentView.frame.size.height/2.0);
if((CELL_TEXTLABEL_HEIGHT + [self getDetailTextSizeForString:detailtextlabel].height) <= CELL_ROW_DEFAULTHEIGHT)
{
yOriginImg -= (CELL_IMGHEIGHT/2.0);
}
photo = [[[UIImageView alloc] initWithFrame:CGRectMake(CELL_LABELS_MARGIN+CELL_TEXTLABEL_WIDTH, yOriginImg, CELL_IMGWIDTH, CELL_IMGHEIGHT)] autorelease];
photo.tag = PHOTO_TAG;
[cell.contentView addSubview:photo];
}
else
{
mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
secondLabel = (UILabel *)[cell.contentView viewWithTag:SECONDLABEL_TAG];
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
}
mainLabel.text = textlabel;
secondLabel.text = detailtextlabel;
cell.badgeString = [NSString stringWithFormat:#"%g",obj.duration];
UIImage *theImage = [UIImage imageNamed:#"right_cell_icon.png"];
photo.image = theImage;
return cell;
}
- (NSString*) getMainTextStringFromMyObject:(MyObject*) obj
{
return obj != nil? obj.name : nil;
}
- (NSString*) getDetailTextStringFromMyObject:(MyObject*) obj
{
return obj.detail != nil ? obj.detail : nil;
}
- (CGSize) getDetailTextSizeForString:(NSString*) str
{
CGSize constraint = CGSizeMake(CELL_TEXTLABEL_WIDTH - (CELL_LABELS_MARGIN * 2), 20000.0f);
return [str sizeWithFont:[UIFont systemFontOfSize:CELL_DETAILTEXTLABEL_FONTSIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
}