iOS Set Height of Expanding TableCell with Table View - ios

I created a TableView with Expandable cell as shown here. In my case the expanded area contains a TextView. My view contains a tag (as label text) and its' meaning (in text view). And things are working fine.
I have come up with a situation where a single tag can have multiple meanings. So I need to show all the meanings. So I got to have that many textview's as many meanings for each tag.
I have added a TableView (with TextView in TableCell) inside the expandable part of the table cell. So can add X number of rows in the expanded table cell with each meaning of the tag in single cell. I want to set the height of TextView, TableView and finally TableViewCell. I tried different ways, but am not able to achieve it. Can you help me achieve it the way I am looking for.
Screen shot of something that I am trying to achieve -
UPDATE :-
My cellForRowAtIndexPath method where I am trying to set properties :-
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Table View TAG = %d ROW = %d", tableView.tag, indexPath.row);
// TABLE VIEW IN THE CELL
if (tableView.tag == 10) { // cell.valuesTv
CannedValueCell *ccell = (CannedValueCell *) [tableView dequeueReusableCellWithIdentifier:#"cannedValueCell"];
if (ccell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CannedValueCell" owner:self options:nil];
ccell = [nib objectAtIndex:0];
}
// Populate valuesTv
ccell.valueTextView.text = [valuesArray objectAtIndex:indexPath.row];
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(valueTextViewTapped)];
[ccell.valueTextView addGestureRecognizer:gestureRecognizer];
//[ccell.valueTextView sizeToFit]; // Makes no difference
// CGRect frame = ccell.valueTextView.frame;
// frame.size.height = ccell.valueTextView.contentSize.height;
// ccell.valueTextView.frame = frame;
NSLog(#"*** TEXTView HEIGHT = %f C_CELL HEIGHT = %f ** TV HEIGHT = %f", ccell.valueTextView.frame.size.height, ccell.frame.size.height, cell.valuesTv.frame.size.height );
// *** TEXTView HEIGHT = 79.000000 C_CELL HEIGHT = 80.000000 ** TV HEIGHT = 80.000000
// AS SET HEIGHT IN STORY BOARD - NO DIFFERENCE
return ccell;
} else {
// MAIN TABLE VIEW
static NSString *cellIdentifier = #"CannedCell";
cell = (CannedCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CannedCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// Set datasource and delegate for the cell's TableView
cell.valuesTv.dataSource = self;
cell.valuesTv.delegate = self;
.......
}
}
Table view delegate method
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.cannedTV) {
if (selectedIndex == indexPath.row)
return 150; //(30 + (80 * valuesArray.count));
else
return 30;
}
return 30;
}
}
This is what the result is :-
I tried various things, searched a lot on net, but couldn't find solution for the following :-
Set height of Text View as much as the contents of it.
The inner table should be completely visible - in all cells full textview should be visible with its complete contents properly. So each cell may have different height.
Thus the outer/main table expandable cell should also be accordingly set. - For this I tried (30 + (80 * valuesArray.count));, but the inner table doesn't occupy that much space.
How to get which textview is tapped ? When textview is tapped, the method valueTextViewTapped is fired, but yet am not able to find which textview is tapped on. How can I pass the indexPath.row to valueTextViewTapped method, so can find which textview was tapped on ??
Can you please guide me set the height of the components accordingly and achieve the requirements. Any help is highly appreciated. Thanks.

A table view and table view controller are very powerful tools.
Based on the information provided, your suggested implementation is satisfactory.
A UITableViewCell can have its height set dynamically using the table view delegate method heightForRowAtIndexPath.
You can respond to a user selecting the UITableViewCell using the table view delegate method didSelectRowAtIndexPath.

Related

Displaying image in sliding menu

I have small question. How to display profile picture and UserFullName and State and Country in single label dynamically from a service in sliding menu like below attached image. TIA
Design tablecell like this or you can also design UIView in sidebar like same.
Programmatically set corner radius of image so it's look round.
Yes you can set all in one label expect to imageview
do this
[_demolabel setText:[NSString stringWithFormat:#" UserFullName \n State Country"]];
And apply your suitable logic for label height and width.
Image you can not add in Label, you need a separate outlet for Image.
Displaying in single label is bit tricky. You have to use NSAttributted Text. After reading the name of the user needed to append a \n to truncate the next line data.
label.numberOFLines = 0; (you have to set this for label)
Best option Use two label one for User name and next one is for location give proper auto layout and spacing between them, then you are done.
Use Custom Cell you can get the image,name,state and country
First you need to create Custom UITableView Cell.In xib file you need to set ImageView,name label and staecountry label also connect(drag in .h).
please import the Quartzcore framework for forming circle
#import <QuartzCore/QuartzCore.h>
in TableView DataSource Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return yourArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.imgViewDetail.image = [UIImage imageNamed:#"imagename.png"];
cell.imgView.layer.borderWidth = 2.0;
cell.imgView.layer.cornerRadius = cell.yourImageView.frame.size.height /2;
cell.imgView.layer.masksToBounds = YES;
cell.labelName.text = #"James Stevens";
cell.labelStateCountry.text = [NSString stringWithFormat:#"%#%#",#"Sydney",#"Australia"];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
Important - You have to give imageView width and height as 200,200 or 100,100 or 50,50....whatever you want to give equal width and height when you set imageView as circle
You can't set UserFullName, State and Country in single label. You need to use two labels, set image like your attached pic, and round corners.
For example:
Imageview.layer.cornerRadius=10;
[Imageview.layer setMasksToBounds:YES];

Change tableview row height based on multiple cell xib

I have a tableview where cells are populated from the xib files. There are 2 cell xib files displaying different content in the tableview dynamically.
I want to set the row height for the tableview based on which cell is being populated. I used heightForRowAtIndexPath to set the height of the row depending on the cell xib. Following is the code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CommentBoxCell *commentBoxCell;
UserCommentCell *userCommentCell;
if ([commentsAndTagsArray count]) {
if (!commentBoxCell){
return commentBoxCell.bounds.size.height;
}
if (!userCommentCell){
return userCommentCell.bounds.size.height;
}
}
//default height of the cell
return 44;
}
Doing this displays nothing in the tableview, just empty cells. Without the heightForRowAtIndexPath, the cells are populated with correct content but with default tableview row height.
How can I set the row height in tableview whose cells are populated from the xib files?
it looks like commentsAndTagsArray does is not nill and have 1 or more objects so it enter the first if, after that it does nothing as your cell's aren't initialized and there's not default return there.
Now heightForRowAtIndexPath: comes before cellForRowAtIndexPath: so you don't have a cell yet at this point, but you should be able to know what kind of cell do you want to present using the indexPath or whatever logic you're using to identify which cell type to create, why don't you use that logic to select the height instead?
You should first instantiate your 2 cells like this somewhere in your viewDidLoad method:
commonetBoxCell = [[[NSBundle mainBundle] loadNibNamed:#"CommentBoxCellNib" owner:self options:nil] firstObject];
userCommentCell = [[[NSBundle mainBundle] loadNibNamed:#"UserCommentCellNib" owner:self options:nil] firstObject];
Then, you should update the height method like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = 44.0;
if (<this is a comment box cell>) {
[commonetBoxCell updateWithData];
height = [commonetBoxCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
}
if (<this is a user comment cell>) {
[userCommentCell updateWithData];
height = [userCommentCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
}
return height;
}

IBOutlet UIView in tableView cell repeating

I have a custom UIView for my custom tableViewCell that seems to be repeating as I scroll down. The first 5 cells will have unique views, but the second set of 5 cells will repeat the UIViews from the first set of cells. I feel like I'm pretty familiar with dequeuing my cells, but I can't seem to reset the UIViews before the cells are reused. I've read plenty of SO answers about repetition when reusing tablebview cells but nothing seems to be working. Could this have something to do with my UIView being an IBOutlet?
Each table view cell has a unique UIBezierPath that is set to the views path property.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* identifier = #"audioTableCell";
OSAudioTableCell *cell = [self.audioTable dequeueReusableCellWithIdentifier:identifier];
if(cell == nil)
{
cell = [[OSAudioTableCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: identifier];
}
Recording * recording = [self.managedDocument.frc objectAtIndexPath:indexPath];
cell.waveView.path = nil;
cell.waveView.minAmpl = [recording.minAmpl floatValue];
NSData * pathData = recording.waveData;
cell.waveView.path = [NSKeyedUnarchiver unarchiveObjectWithData:pathData];
[cell setImageSize:cell.waveView.bounds.size];
}
I've already tried setting the UIView to nil in my prepareForReuse method in my custom tableview cell, but it made no difference.

UITableView with Various Custom Cells of differing heights within UIView

I am building a IOS app homepage which basically consists of the following structure -
Which is basically a UIView which contains a nested UIScrollView which inturn contains a TableView with 3 Custom Cells.
I pull data out of a dynamic array and filter it into the relevant cell - all works fine other than two issues I cant work out -
1- The custom cells are different heights in the storyboard but when the app is compiled they are always the same height - is it possible to set an auto height on the UITableView Row? If not can anyone explain how I can apply the correct height to each cell?
2- The TableView / View which wraps the table view need to expand to make all dynamic cells visible - how can I achieve this?
below is my tableview method for reference -
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =#"CellFeed";
static NSString *CellIdentifierArtNo =#"CellArtRecNo";
static NSString *CellIdentifierBook =#"CellBooking";
UITableViewCell *cell;
feedData *f = [self.HpFeedArray objectAtIndex:indexPath.section];
NSString * ArtPString = #"articleP";
NSString * ArtNoPString = #"article";
NSString * ArtBook = #"booking";
if([f.FeedGroup isEqualToString:ArtPString]){
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
CellHp_RecArticleWithImage *cellImage = (CellHp_RecArticleWithImage *)cell;
cellImage.selectionStyle = UITableViewCellSelectionStyleNone;
cellImage.artTitle.text = f.FeedTitle;
cellImage.artImg.text = f.FeedDesc;
cellImage.artDate.text = f.FeedDate;
cellImage.textLabel.backgroundColor=[UIColor clearColor];
return cellImage;
}
if([f.FeedGroup isEqualToString:ArtBook]){
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierBook
forIndexPath:indexPath];
CellHp_BookingAlert *cellBook = (CellHp_BookingAlert *)cell;
cellBook.selectionStyle = UITableViewCellSelectionStyleNone;
cellBook.HeadlineLbl.text = f.FeedTitle;
cellBook.TextBoxLbl.text = f.FeedDesc;
//cellBook.DateLbl.text = f.FeedDate;
return cellBook;
}
else{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierArtNo
forIndexPath:indexPath];
CellHp_RecArticleNoImage *cellNoImage = (CellHp_RecArticleNoImage *)cell;
cellNoImage.selectionStyle = UITableViewCellSelectionStyleNone;
cellNoImage.artTitle.text = f.FeedTitle;
cellNoImage.artImg.text = f.FeedDesc;
cellNoImage.artDate.text = f.FeedDate;
cellNoImage.textLabel.backgroundColor=[UIColor clearColor];
return cellNoImage;
}
Cheers
It looks like you've got custom UITableViewCell subclasses like CellHp_RecArticleNoImage or CellHp_BookingAlert (may I suggest renaming them to something a little less headache-inducing? ;) ).
In that case, if you only have 3 different cell types, you could do this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell* cell = [tableView cellForAtIndexPath:indexPath];
if ([cell isKindOfClass:[CellHp_BookingAlert class])
{
return 123.0;
}
else if ([cell isKindOfClass:[CellHp_RecArticleNoImage class])
{
return ...
}
...
}
Or, you could make all your custom classes implement a height method for a cleaner solution and in heightForRowAtIndexPath: you could just get the cell and call its height method.
Re. Question 2, use UIView's sizeToFit method as Tim mentioned.
You need to implement below method to identify the height of cell.
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath
*)indexPath;
You can derive static or dynamic (data driven) cell heights from the storyboard by dequeuing them in heightForRowAtIndexPath according to the procedure outlined here: Retrieve custom prototype cell height from storyboard?
I'm not exactly sure I understand this question, but you can get the contentSize of the table view if you're trying to size the table to fit the content.

iOS xcode, adding UILabel subview to custom table cell, label text does not update on screen

I've created a custom UITableViewCell class, and used the layoutSubviews method to add a custom label. Like this:
- (void)layoutSubviews
{
[super layoutSubviews];
if (statusLabel == nil)
{
statusLabel = [[UILabel alloc]initWithFrame:CGRectMake(430.0, 10.0, 100.0, 20.0)];
[statusLabel setTextAlignment:UITextAlignmentRight];
[statusLabel setText:#"Status, set in code"];
statusLabel.tag = 1;
[self.contentView addSubview:statusLabel];
}
}
As you can see, I have set the initial text of the label to "Status, set in code".
In the table view controller I set the text for this custom label in the cellForRowAtIndexPath method, like so:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int index = [indexPath row];
NSString *introducerString =[introducers objectAtIndex:index];
NSArray *parts = [introducerString componentsSeparatedByString:#","];
static NSString *MyIdentifier = #"Requester";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[DanceCardCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MyIdentifier] autorelease];
}
UIImage *image = [UIImage imageNamed:#"1.jpg"];
[cell.imageView setImage:image];
cell.textLabel.text = [parts objectAtIndex:1];
cell.detailTextLabel.text = #"Some text";
UILabel *statusLabel = (UILabel *)[cell viewWithTag:1];
statusLabel.text = #"Did it!";
return cell;
}
I'm using one table view to display two lists, depending on which of two buttons is pressed. When a button is pressed the appropriate table view controller is attached to the table view, and the reloadData method is called to trigger display of the new data. The new data does display, but the custom label text, which should read "Did it!" reads "Status, set in code ...", until I switch lists again twice.
How can I get the new text for the custom label to update straight away? I have checked the official documentation and cannot find any reference to refreshing a cell's display after updating its custom content.
Here is a screen shot to demonstrate what happens: http://www.dsbsystems.co.uk/images/xcode1.png
You're initializing the cell and immediately attempting to find the statusLabel with tag 1 inside it. layoutSubviews hasn't had the opportunity to be called yet, and so the label hasn't been created and added. (I suggest overriding the designated initializer method on your table view cell and creating the label there.)
Because of this, when you try to pull out statusLabel, it becomes nil because there's no such view, and messaging (calling a method on) nil simply does nothing (actually, it returns nil). You will need to watch out for this going forward if you're used to things blowing up with e.g. null reference exceptions.
When the cell is requested again, a new cell isn't needed because it's available from the reuse queue, and the label will be found correctly.

Resources