Insert Dynamic Section Headers in UITableView - iphone

I have a UITableView in which i want to add the section headers dynamically as the user clicks add button. The user should also be able to delete the headers if they dont need it. Under each header the user should be able to add relevant list of items. And apart from that the user should be able to insert rows dynamically under selected section only. Please suggest some ideas to achieve this functionality. Thanks in advance.

You can achieve this by removing and then adding that section again, this will cause a call to tableView:titleForHeaderInSection:
Assume your section index is 0:
BOOL shouldShowHeader;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
shouldShowHeader ? #"Your Header" : nil;
}
- (IBAction)buttonAction:(id)sender
{
shouldShowHeader = !shouldShowHeader;
NSIndexSet *set = [NSIndexSet indexSetWithIndex:0];
[self.tableView beginUpdates];
[self.tableView deleteSections:set withRowAnimation:UITableViewRowAnimationNone];
[self.tableView insertSections:set withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
Footer works the same way.

I will tell for dynamic section header. Keep a flag and set to 0 initially. When User clickes on button in that buttonClick method set flag to 1 and reload tableView.
-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(flag)
return aView;//alloc init aView and return.
else
return nil.
}
Similarly for dynamic rows have a array and numberOfRows be array.count.
On click of button insert one more item in array and reload Table.
I hope this help.

When user clicks on button in this method set a flag and reload your tableview and then do it..
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(flag)
{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,320, 30)];
return headerView;
}
else
return nil;
}
and you can delete header in table view like this......
If you want to remove the table's header view, just set the myTable.tableHeaderView property to nil. If what you have is actually a section header, then you need to return nil from the viewForHeaderInSection method and call [myTableView reloadData]
and i hope this will work fine.

Related

How to hide custom check mark in table view

I have a UITableiew that I want to be able to display a custom check mark when the row is selected (tapped), however, if there is a check mark on any of the other rows, it must be hidden. What is the best way to do this? The IF... doesn't seem to work at all, it will not hide and unhide the check mark as I thought it would.
Thanks in advance.
-PaulS.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
home_2_CustomCell *cell = (home_2_CustomCell*)[tableView cellForRowAtIndexPath:indexPath];
//This will hide the selected row...
cell.imageViewDidSelectRow.hidden = YES;
// if (cell.imageViewDidSelectRow.hidden = NO){
// cell.imageViewDidSelectRow.hidden = YES;
// }
}
1) Maintain a tag in class level as an NSIndexPath variable.
2) Whenever a cell is selected make note of the indexPath and reload the table view.
3) In cellForRowAtIndexPath delegate check for this variable and set marks accordingly.
4) This will not be costly if you have the cell with less information.
You can get the each cell of tableview by this code
UITableViewCell *cell=[product_table cellForRowAtIndexPath:[NSIndexPath indexPathForRow:clickedTag inSection:0]];
make one for loop.
for(int i=0;i<[tabledata count];i++){
cell.imageViewDidSelectRow.hidden = YES;
}
for each cell except the current row which is selected and you got only one image displayed for the current row.

Clearing TableView contents

Can any one help me by providing code for how to clear all the table view cell contents.
The tableview when a button is pressed gets reloaded but does not get cleared
Thanks
Rakesh
For clearing a tableView, you just remove all objects from the array that is populating your table and you reload the tableView after that.
[myArray removeAllObjects];
[self.tableView reloadData];
Set a bool tableIsEmpty and set the number of rows in the tableview to either 0 (table is empty) or the arrays count according to this BOOl in
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
Of cousre you have to set tableIsEmpty = YES, when the button is pressed and to NO again when theres data loaded.
Then call
[self.tableView reloadData];
Not tested but should work shouldnt it?
You can just add one variable as flag before reloading the table.
makeEmpty = YES;
[tableview reloadData];
makeEmpty = NO;
Then in the tableview delegate method
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(makeEmpty)
return 0;
}

Edit & delete multiple rows in UITableView simultaneously

In my app I need to delete multiple rows in a table, edit the table and get a check box beside the table. When checked then the table cells are deleted. It is like the iPhone message app. How can I do this, please help me.
If I understand your question correctly, you essentially want to mark UITableViewCells in some way (a checkmark); then, when the user taps a master "Delete" button, all marked UITableViewCells are deleted from the UITableView along with their corresponding data source objects.
To implement the checkmark portion, you might consider toggling between UITableViewCellAccessoryCheckmark and UITableViewCellAccessoryNone for the UITableViewCell's accessory property. Handle touches in the following UITableViewController delegate method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *c = [tableView cellForRowAtIndexPath:indexPath];
if (c.accessoryType == UITableViewCellAccessoryCheckmark) {
[c setAccessoryType:UITableViewCellAccessoryNone];
}
//else do the opposite
}
You might also look at this post regarding custom UITableViewCells if you're wanting a more complex checkmark.
You can set up a master "Delete" button two ways:
The IB approach
The programmatic approach
In either case, eventually a method must be called when the master "Delete" button is pressed. That method just needs to loop through the UITableViewCells in the UITableView and determined which ones are marked. If marked, delete them. Assuming just one section:
NSMutableArray *cellIndicesToBeDeleted = [[NSMutableArray alloc] init];
for (int i = 0; i < [tableView numberOfRowsInSection:0]; i++) {
NSIndexPath *p = [NSIndexPath indexPathWithIndex:i];
if ([[tableView cellForRowAtIndexPath:p] accessoryType] ==
UITableViewCellAccessoryCheckmark) {
[cellIndicesToBeDeleted addObject:p];
/*
perform deletion on data source
object here with i as the index
for whatever array-like structure
you're using to house the data
objects behind your UITableViewCells
*/
}
}
[tableView deleteRowsAtIndexPaths:cellIndicesToBeDeleted
withRowAnimation:UITableViewRowAnimationLeft];
[cellIndicesToBeDeleted release];
Assuming by "edit" you mean "delete a single UITableViewCell" or "move a single UITableViewCell," you can implement the following methods in the UITableViewController:
- (void)viewDidLoad {
[super viewDidLoad];
// This line gives you the Edit button that automatically comes with a UITableView
// You'll need to make sure you are showing the UINavigationBar for this button to appear
// Of course, you could use other buttons/#selectors to handle this too
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//perform similar delete action as above but for one cell
}
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
//handle movement of UITableViewCells here
//UITableView cells don't just swap places; one moves directly to an index, others shift by 1 position.
}
You can put 1 UIButton lets call it "EDIT" and wire up it to IBAction. In IBAction write so you will be able to do as per your requirement.
-(IBAction)editTableForDeletingRow
{
[yourUITableViewNmae setEditing:editing animated:YES];
}
This will add round red buttons on the left hand corner and you can click on that Delete button will appear click on that and row will be deleted.
You can implement delegate method of UITableView as following.
-(UITableViewCellEditingStyle)tableView: (UITableView *)tableView editingStyleForRowAtIndexPath: (NSIndexPath *)indexPath
{
//Do needed stuff here. Like removing values from stored NSMutableArray or UITableView datasource
}
Hope it helps.
you want to be looking for deleteRowsAtIndexPath, with all your code squeezed between [yourTable beginUpdates] & [yourTable endUpdates];

Button added to custom section header view disappears when row is deleted

Just came across some very strange behavior in my app. I've recreated the problem in a simplest-case scenario:
NSMutableArray *data;
- (void)viewDidLoad {
[super viewDidLoad];
data = [[NSMutableArray arrayWithObjects:#"1", #"2", #"3", nil] retain];
}
- (UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section {
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 32.0)];
header.backgroundColor = [UIColor lightGrayColor];
[header addSubview:self.button];
return header;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[data removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
cell.textLabel.text = [data objectAtIndex:indexPath.row];
return cell;
}
- (void)dealloc {
[super dealloc];
}
Every time I delete a row; the button in my header disappears! This happens no matter what type of rowAnimation I use. If I scroll the table up so that the header scrolls off; the button returns when the header returns. The button is created in the xib file.
I can work around it in one of 2 ways:
Reloading the tableView data after the delete; with a delay so that the deletion animation completes first.
Creating the button in viewForHeaderInSection instead of in the interfaceBuilder.
I'd really like to understand what's going on here. Where is the button going? I've confirmed that viewForHeaderInSection is called when I delete a row.
Edit I tried changing it so that the button is created in viewForHeader, instead of in the xib, but it's causing other strange issues... when I create or delete the button, I am setting certain properties such as the title and enabled depending on how many items there are in the table. When I delete the last row in the table, I don't see the update in text and enabled status until I scroll the button off the screen and back on again.
Because you only have one instance of your button, if the table view decides to create a new header view then the button will be removed from its current parent and moved to the new one. Even if you only have one section in your table, the table view may be doing some strange things internally and recreating header views off-screen so you can't rely on just one being in existence at any one time.
You should create the button in viewForHeaderInSection: and work around your other problems. Rather than only updating the button properties in viewForHeaderInSection you should handle any delete events so that deleting a row will also update the button.
Where is your implementation of the delegate method tableView:heightForHeaderInSection: ? That is necessary for tableView:viewForHeaderInSection: to work correctly. Check the docs.
Reference for UITableView delegate
I've confirmed that
viewForHeaderInSection is called when
I delete a row.
Have you confirmed that viewForHeaderInSection is called for the particular header with the added button?
Then, try adding
[header bringSubviewToFront:self.button];
after adding the button.
Well I at least managed to get around my issue... I made an iVar and property for the view that I create in viewForheaderAtSection, and then I only create a new view if I don't have one already. Otherwise I just return the header I already had; something like this:
- (UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section {
if (!self.myHeader){
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 32.0)];
header.backgroundColor = [UIColor lightGrayColor];
[header addSubview:self.button];
self.myHeader = header;
[header release];
}
return self.myHeader;
}
This works, but it would still be great to understand what exactly is going on. As far as I can tell, viewForHeaderInSection is being called by the system, but then the instance of the view that I return in that method is not actually being used / shown; at least not until I do something that causes the view to redraw...

iPhone app development : How can i get a table view in which whn i click on a cell a text view should expand just below that cell...?

How can i get a table view in which whn i click on a cell a text view should expand just below that cell it should look like clicking on a button an it will create a text view in between clicked button and its below button...
i m trying to create a pictorial view...
tabel view:
button 1 >
button 2 >
button 3 >
table view:
button 1 >
button 2 v
__________
.
.
. text view
.
----------
button 3 >
plz solve my problem i m new for iphone app development....
I dont think that this can be done the way u want it, because once the TableView is loaded it is loaded, and if even if you manage to push some extra cells in between, the Table View will not change until it is loaded again.
TableView is loaded in two scenarios i.e
1. When Loading the view
2. While scrolling within the TableView.
my advice is to show a popup window kind of thing...
- (UITableViewCell *)valueForSelectedRow {
UITableViewCell *cell = [self.AccountTable cellForRowAtIndexPath:[self.AccountTable indexPathForSelectedRow]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Get value
UITableViewCell *cell = [self valueForSelectedRow];
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height);
UITextview *txtview = [[UITextView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 150.0f, 25.0f)] autorelease];
[cell addSubview:txtview];
[cell sizeToFit];
//...
....
You might insert a row just under the selected one.
The steps are:
Create an instance of NSIndexPath for the new row
Update your datasource (insert a special object containing the information for your text view). Notice that the datasource object must be mutable (e.g. NSMutableArray).
Insert new row to the table
Sample implementation may look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// 1
NSIndexPath *newRowIndexPath = [NSIndexPath indexPathForRow:(indexPath.row + 1) inSection:indexPath.section];
// 2 (datasource has to be mutable)
[self.datasource insertObject:[NSDictionary dictionaryWithObject:#"THE_TEXT_FOR_YOUR_TEXTVIEW"] atIndex:newRowIndexPath.row];
// 3
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newRowIndexPath] withRowAnimation:UITableViewRowAnimationBottom];
}
Notice that in addition to this code you will have to treat the "special" row differently in tableView:cellForRowAtIndexPath: method...
Cheers.
Michael.