Currently I am adding an icon to the right-side of one row and toggle the light on selection of that specific row.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
...
...
NSUInteger row = [indexPath row];
if(row == 3)
{
//Draw bulb in row
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bulb-on.png"]];
//Instead of image, draw toggle-switch here
}
else
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
How can I, instead of that image, draw a usable toggle-switch?
Property accessoryView is just a usual UIView, so you can add any subviews to it:
UISwitch *toggleSwitch = [[UISwitch alloc] init];
cell.accessoryView = [[UIView alloc] initWithFrame:toggleSwitch.frame];
[cell.accessoryView addSubview:toggleSwitch];
P.S. Don't forget to release allocated objects!
Related
I am attempting to update a label inside a cell(note, this is NOT the cell's label text. Its another custom label inside of the cell) after the user selects a value from a previous screen and the nav controller popping them back.
However, when I call reloadData, instead of the label in the cell being cleaned and the new value being placed, its actually stacking on top of what was there already. Like if you took the number 200 and placed a 50 on top of it. You get a weird mesh of the 0 and 5 on top of each other.
Any ideas on how to adjust this? Do I have to reset the label's text to "" every view did appear? and if so, what's the best way to do this, I've tried in the cellForRowAtIndexPath method, but no change.
cellforRowAtIndexPath code
// Set up the cell...
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// get the dictionary object
NSDictionary *dictionary = [_groups objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"key"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
//label for currently selected/saved object
_currentSetting = [[UILabel alloc] initWithFrame:CGRectMake(160, 8, 115, 25)];
[_currentSetting setFont:[UIFont systemFontOfSize:14]];
_currentSetting.backgroundColor = [UIColor clearColor];
_currentSetting.textColor = [UIColor blueColor];
_currentSetting.textAlignment = NSTextAlignmentRight;
_currentSetting.text = [NSString stringWithFormat:#""];
_currentSetting.text = [NSString stringWithFormat:#"%# mi",[setting.val stringValue]];
[cell.contentView addSubview:_currentSetting];
return cell
You are recreating the label and re-adding it every time the cell gets refreshed. All of your cell subviews should only be added when you create the cell the first time.
So in your code you create a cell and all subviews the first time. Then if you need a new cell for scrolling or any other reason you get a reusable cell that has already had all the subviews added to it (re-usable...). Then you go through the process of adding the subviews (again) so now that cell contains the subviews from the previous owner (data) of that cell and the new owner (data) of that cell. That is why they appear stacked on top of eachother when you reload the data.
seudo code:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil) {
//Add all subviews here
}
//Modify (only modify!!) all cell subviews here
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UILabel *customLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
customLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,44)];
customLabel.tag = 123;
[cell addSubview:customLabel];
} else {
customLabel = (UILabel *)[cell viewWithTag:123];
}
customLabel.text = #"Some nice text";
return cell;
}
I am new to iphone.I am struck in my project at some task (i.e),I have a table view with 66 rows.In that i am placed different book names for each cell and place a download button to each book.My requirement is when we click on download button it shows the progress view in that particular cell only but i am getting in that particular cell but when i am drag the tableview it will shows the progress views in some that cells also.It is because of dequeue reusability concept but i dont know how to avoid this problem.I want even after drag the tableview it shows the progress view on the cell which i am click the download button (cell)
here is my code below..
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 66;
}
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UIButton *downloadButton = nil;
CustomCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
//here custom cell is another class in that we have the title label declaration
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
downloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
downloadButton.frame = CGRectMake(220,10,50,30);
[downloadButton setImage:[UIImage imageNamed:#"download.png"] forState:UIControlStateNormal];
[downloadButton addTarget:self action:#selector(downloadButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
downloadButton.backgroundColor = [UIColor clearColor];
downloadButton.userInteractionEnabled = YES;
downloadButton.highlighted = YES;
downloadButton.tag = indexPath.row;
NSLog(#"tag is %d",indexPath.row);
[cell.contentView addSubview:downloadButton];
}
NSString *titleLabel = [[appDelegate getBookNames]objectAtIndex:indexPath.row];
cell.TitleLabel.text = titleLabel;
return cell;
}
-(void)downloadButtonClicked:(id)sender{
int index = [sender tag];
NSLog(#"index of the cell is %d",index);
UIButton *button = (UIButton*)sender;
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
NSLog(#"label text =%#",titleLabel.text);
selectedBookTitle = titleLabel.text;
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSMutableArray *allDownloadLinks;
biblePlayerViewController = [[BiblePlayerViewController alloc]init];
allDownloadLinks = [biblePlayerViewController allDownloadLinks];
NSLog(#"all Download Links are %#",allDownloadLinks);
biblePlayerViewController.indexOfSelectedBookTitle = [[appDelegate getBookNames]indexOfObject:selectedBookTitle];
Download* download = [Download downloadWithTitle:selectedBookTitle url:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.audiotreasure.com/%#.zip",[allDownloadLinks objectAtIndex:(biblePlayerViewController.indexOfSelectedBookTitle)]]]PathtoSave:documentsPath];
[[DownloadManager sharedDownloadManager] queueDownload: download];
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
progressView.frame = CGRectMake(10, 40, 300, 20);
[tableViewCell.contentView addSubview:progressView];
}
screen shot of my project is [output of my above code which is in simulator]
you should nil the cell every time in cellForRow. This way it will not be re-used and allocated every time. It should work pretty fine in your case as your tableview is not very large. Just add the following line before cell == nil check:
cell = nil;
It should work now.
I have the same problem, one way to avoid it is to just lock the scrolling ability of the table during the download.
When i checked a cell, the image associated is changed, but when i had scrolled down and up, the cell got its default image this is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self->tableContents objectForKey:
[self->sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
UIImageView *unchecked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"unchecked.png"]];
UIImageView *checked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"checked.png"]];
BOOL bChecked = NO;//By default, it's unchecked, so NO
/// Assign cell according to `bChecked`
cell.accessoryView = (bChecked ? checked : unchecked);
return cell;
}
EDIT:
I have edited my code to look as above, but i still get the issue, the default image is getting back when i scroll up my table view.
EDIT 2:
#Openside: So according to your approach, my snippet should look like this:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self->tableContents objectForKey:
[self->sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
}
NSUInteger row = [indexPath row];
textClass *myText = (textClass*)[listData objectAtIndex:row];
cell.textLabel.text = myText.text;
UIImageView *unchecked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"unchecked.png"]];
UIImageView *checked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"checked.png"]];
cell.accessoryView = (myText.isChecked ? checked : unchecked);
return cell;
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
textClass *myText=[[textClass alloc]init];
myText.isChecked=YES;
}
I got this exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString text]: unrecognized selector sent to instance 0x673bc'
The line indicating the exception issue is this (in cellForRowAtIndexPath delegate method):
cell.textLabel.text = myText.text;
I have added the class textClass although i am not so convinced, i think i can use a property in the holder class of my UITableView.
As Openside said, while scrolling, the cell will come from dequeue. So, we need to assign image according to new state.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = ...; ///< reuse a created cell.
if(cell == nil) {
cell = ...; ///< create a new cell
}
BOOL bChecked = ...///< Decide the cell checked or not.
/// Assign cell according to `bChecked`
cell.accessoryView = (bChecked ? imgChecked : imgNonChecked);
return cell;
}
Edit:
As for me, I will decide check status by the method indexPathForSelectedRow of tableView. I assume your table view is not multiple selection. It selects only one row at one time.
So, I decide the checked status by following. Because the tableView holds the information about which indexPath is selected.
NSIndexPath *selIndexPath = [tableView indexPathForSelectedRow];
BOOL bChecked = [indexPath isEqual:selIndexPath];
The problem is that the cell will be refreshed (or reused hence the dequeueReusableCellWithIdentifier ) when you scroll it out of view and then back into view. You need to have a flag on your source object to say if it's checked or not and then add an if statement to determine if the checked.png or unchecked.png image is used.
However, looking at your code the source object is just text, it may be worth creating a subclassed NSObject with two properties
text and
checked
Then your cellForRowAtIndexPath code can determine which image to show.
I hope that helps.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
}
NSUInteger row = [indexPath row];
textClass *myText = (textClass*)[listData objectAtIndex:row];
cell.textLabel.text = myText.text;
UIImageView *unchecked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"unchecked.png"]];
UIImageView *checked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"checked.png"]];
/// Assign cell according to `bChecked`
cell.accessoryView = (myText.isChecked ? checked : unchecked);
return cell;
}
#interface textClass : NSObject {
#private
NSString *_text;
BOOL _isChecked;
}
#property (nonatomic, retain) NSString *text;
#property (nonatomic, assign) BOOL isChecked;
#end
#implementation textClass
#synthesize text = _text;
#synthesize isChecked = _isChecked;
#end
Ok so here I have created a class called textClass it has two properties text and isChecked. When you load your view populate an NSMutableArray (listData) with these objects using the text you were previously using. When your cell gets checked set the isChecked property to YES when the cell gets reused this property has retained its state outside of the delegate method and should render correctly.
Put the complete code in brackets :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self->tableContents objectForKey:
[self->sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
NSUInteger row = [indexPath row];
textClass *myText = (textClass*)[listData objectAtIndex:row];
cell.textLabel.text = myText.text;
UIImageView *unchecked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"unchecked.png"]];
UIImageView *checked = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"checked.png"]];
cell.accessoryView = (myText.isChecked ? checked : unchecked);
}
return cell;
}
This should definitely work.
I am having a problem setting a UIImageView or UIView on the cell of the Grouped table on the iPhone.
For this I am using this code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self.tableContents objectForKey:[self.sotreKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
if(indexPath.section == 1 && indexPath.row ==1)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 14, 40, 40)];
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"Back.png",nil]];
[cell.contentView addSubview:imageView];
[imageView release];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
But it is not placed on the cell . When ever I select the row it will display for that time only, what is the problem?
Does anyone have any idea what the problem is. I think the image is getting overwritten by the cell .
Thanks in advance
try making
cell.accessoryType = UITableViewCellAccessoryNone;
It seems that you are adding image on accessory view.
If yes, you can add cell.accessoryView = imageView;
I do have some ideas of what might be happening.
You are adding an image view to the contentView then you are setting the text of the textLabel which is a part of the contentView and is probably sitting on top of the image. Try this and see if you can at least see your image on the left side.
cell.imageView.image = [UIImage imageNamed:#"Back.png"];
Now when you dequeue cells you need to remember that all the views you added last time you created the cell are still there, so as you scroll you will just be stacking back buttons on top of each other.
Also the following line [tableView deselectRowAtIndexPath:indexPath animated:YES]; is dead code because it occurs after a return statement. You might want to place that in the delegate call – tableView:willDisplayCell:forRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self.tableContents objectForKey:[self.sotreKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
if(indexPath.section == 1 && indexPath.row ==1)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(240, 14, 40, 40)];
imageView.image = [UIImage imageNamed:#"Back.png"];
[cell.contentView addSubview:imageView];
[imageView release];
}
cell.textLabel.text = [listData objectAtIndex:indexPath.row];
return cell;
}
Make sure that your image is named "Back.png" not "back.png" because the iOS on the phone is key sensitive.
I am trying create an accordion type of uitableviewcell that, when the user selects the cell, it expands to display a detailed info view inline similar to how the digg app works. I initially tried replacing the current tablecell with a customcell in cellForRowAtIndex, however the animation looks a bit choppy as you can see the cell being replaced and overall the effect doesn't work too well.
If you look at the digg app and others who have done this it seems that they aren't replacing the current cell but instead perhaps adding a subview to the cell? The original cell however doesn't seem to animate at all and only the new view accordions into the table.
Does anyone have any ideas how to accomplish a similar effect?
I have made some progress using neha's method below and while the cell is animating the correct way it is wreaking havoc with the other cells in the table. What I have done is subclassed UITableViewCell with a custom class which contains an instance of a UIView which actually draws the view which I then add to the table cell's contentview.
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
if (selected) {
[self expandCell];
}
}
-(void)expandCell {
self.contentView.frame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 110);
}
Here are all the table delegate methods I am using:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = #"SearchCell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)];
theText.text = #"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:#"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
selectedIndex = indexPath.row;
isSearching = YES;
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
return 110;
}
return rowHeight;
}
It seems now that the cell is expanding but not actually being refreshed so the labels, and textfield aren't being shown. They do however show up when I scroll the cell off and on the screen.
Any ideas?
The Apple way to do is quite simple.
First, you'll need to save the selected indexPath row:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedRowIndex = [indexPath retain];
[tableView beginUpdates];
[tableView endUpdates];
}
I'll explain the begin/end updated part later.
Then, when you have the currently selected index, you can tell the tableView that it should give that row more space.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//check if the index actually exists
if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {
return 100;
}
return 44;
}
This will return height 100 for the selected cell.
Now we can go back to the begin/end updates. That block triggers the reload of all tableView geometry. Moreover, that block is animated, which eventually gives the impressions of the row expanding.
Pawel's beginUpdates/endUpdates trick is good, and I often use it. But in this case you simply need to reload the rows that are changing state, ensuring that you correctly reload them with the desired cell type, and that you return the correct new cell height.
Here is a complete working implementation of what I think you're trying to accomplish:
.h:
#import <UIKit/UIKit.h>
#interface ExpandingTableViewController : UITableViewController
{
}
#property (retain) NSIndexPath* selectedIndexPath;
#end
.m:
#implementation ExpandingTableViewController
#synthesize selectedIndexPath;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier1 = #"Cell1";
static NSString *CellIdentifier2 = #"Cell2";
UITableViewCell *cell;
NSIndexPath* indexPathSelected = self.selectedIndexPath;
if ( nil == indexPathSelected || [indexPathSelected compare: indexPath] != NSOrderedSame )
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %d", indexPath.row];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier2] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat: #"cell %d", indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat: #"(expanded!)", indexPath.row];
}
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( self.selectedIndexPath != nil && [self.selectedIndexPath compare: indexPath] == NSOrderedSame )
{
return tableView.rowHeight * 2;
}
return tableView.rowHeight;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray* toReload = [NSArray arrayWithObjects: indexPath, self.selectedIndexPath, nil];
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths: toReload withRowAnimation: UITableViewRowAnimationMiddle];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
#end
If you don't want to reload the cell (you want to keep your existing cell and just change the size, and likely add/remove some subviews), then simply do the beginUpdates/endUpdates trick in didSelectRowAtIndexPath:, and call some method on your cell to incite the layout change. beginUpdates/endUpdates will prompt the tableView to re-query the heights for each cell - so be sure to return the correct value.
Create a class that subclasses UITableviewcell in your project. Create this class' nib and set its parent to be the class in your project with tableview and override its -
(void)setSelected:(BOOL)selected animated:(BOOL)animated
Write methods contractCell() and expandCell() in this class, and provide the height of the cells you want in expandCell method. Call this methods appropriately based on some flags set to identify wheather the cell is in expanded state or contracted state. Use your tableview's
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
method to handle selection of cells.
Replace your cellForRowAtIndexPath function with this one.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
static NSString *CellIdentifier = #"SearchCell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0,
10.0, cell.contentView.bounds.size.width
-20, 22.0)];
theText.text = #"Title Text";
[cell.contentView addSubview:theText];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 +
46.0, cell.contentView.bounds.size.width - 20, 40.0)];
textField.borderStyle = UITextBorderStyleLine;
[cell.contentView addSubview:textField];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0,
88.0, cell.contentView.bounds.size.width - 20, 22.0)];
testLabel.text = [NSString stringWithFormat:#"Some text here"];
[cell.contentView addSubview:testLabel];
[theText release];
[textField release];
[testLabel release];
return cell;
} else {
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]];
return cell;
}
}
create array wof dictionary which have a key Select_sts which is 0 in start when click its change 1
accourding u change table
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 40.0)];
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.opaque = NO;
headerLabel.textColor = [UIColor blackColor];
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.frame = CGRectMake(5.0, 10.0, 300.0, 20.0);
headerLabel.text=[NSString stringWithFormat: #"PNR %#",[[record objectAtIndex:section] objectForKey:#"number"]];
customView.backgroundColor=[UIColor whiteColor];
btn_openClose.tag=section+10000;
btn_openClose.backgroundColor=[UIColor clearColor];
// [btn_openClose setImage:[UIImage imageNamed:#"down_arrow.png"] forState:UIControlStateNormal];
[btn_openClose addTarget:self action:#selector(collapseExpandButtonTap:) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:btn_openClose];
}
- (void) collapseExpandButtonTap:(id) sender{
int indexNo=[sender tag]-10000;
// NSLog(#"total_record %#",[total_record objectAtIndex:indexNo]);
NSMutableDictionary *mutDictionary = [[total_record objectAtIndex:indexNo] mutableCopy];
if([[mutDictionary objectForKey:#"Select_sts"] integerValue]==0)
[mutDictionary setObject:[NSNumber numberWithInt:1] forKey:#"√"];
else
[mutDictionary setObject:[NSNumber numberWithInt:0] forKey:#"Select_sts"];
[total_record replaceObjectAtIndex:indexNo withObject:mutDictionary];
// [table_view beginUpdates];
// [table_view reloadData];
// [table_view endUpdates];
NSMutableIndexSet *indetsetToUpdate = [[NSMutableIndexSet alloc]init];
[indetsetToUpdate addIndex:indexNo]; // [indetsetToUpdate addIndex:<#(NSUInteger)#>]
// You can add multiple indexes(sections) here.
[table_view reloadSections:indetsetToUpdate withRowAnimation:UITableViewRowAnimationFade];
}