I'm creating a custom UITableView with expand / collapse functionality. When the user taps in a table section, new rows are inserted using this code:
[self.tableView beginUpdates];
NSMutableArray *arrIP = [NSMutableArray new];
for (NSInteger i=0; i<[rows count]; i++){
#autoreleasepool {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:section];
[arrIP addObject:indexPath];
}
}
[self.tableView insertRowsAtIndexPaths:arrIP withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
Everything works fine but sometimes the tableView don't fit well to their content size. My problem is according to some cells that are drawn behind the expanded section that are touched when I'm scrolling up.
Here's the code to draw sections:
- (UIView *)tableView:(UITableView *)theTableView viewForHeaderInSection:(NSInteger)section {
id sectionKey = [_dataSource objectAtIndex:section][#"section"];
CGFloat sectionHeight = [[_dataSource objectAtIndex:section][#"header_height"] floatValue];
if ([sectionKey isKindOfClass:[NSString class]] && [sectionKey isEqualToString:#"info"]){
OptionCell *cell = [theTableView dequeueReusableCellWithIdentifier:OptionCell.cellIdentifier];
if (cell == nil){
cell = [[OptionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:OptionCell.cellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
return cell;
}else if ([sectionKey isKindOfClass:[NSString class]] && [sectionKey isEqualToString:#"history"]){
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"ExpandedHeader" owner:self options:nil];
ExpandedHeader *headerView = [nibArray objectAtIndex:0];
headerView.BTN_loadData.tag = section;
[headerView.BTN_loadData addTarget:self action:#selector(loadData:) forControlEvents:UIControlEventTouchUpInside];
[headerView setFrame:CGRectMake(0, 0, self.tableView.frame.size.width, sectionHeight)];
return headerView;
}
}
I don't understand what I'm doing wrong.
Thanks in advance!
Related
My Custom tableview cell content getting empty after scrolling.So pls help me with this.
My custom cell has 8 buttons and a label.First I'm showing only label that has title and on selection I'm expanding the cell and showing all buttons.So, when I select few buttons and I do scrolling,buttons that I selected getting refreshed or get back to normal state.Here is the code.Pls help me with this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"newFilterCell";
newFilterCell *cell = (newFilterCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"newFilterCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell.contentView.superview setClipsToBounds:YES];
}
cell.QuestionLabel.text=[orderArray objectAtIndex:indexPath.row];
NSArray * arr = [filterInfo objectForKey:[orderArray objectAtIndex:indexPath.row]];
int val = 0;
NSLog(#"%#",cell.subviews);
NSArray * cellViews = cell.contentView.subviews;
if (arr.count>0)
{
for (int i=1; i<=8; i++) {
if (i<=arr.count) {
UIButton * target = (UIButton*)[cell viewWithTag:i];;
[target setTitle:[arr objectAtIndex:i-1]forState:UIControlStateNormal];
[target addTarget:self action:#selector(selectButton:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[[cell viewWithTag:i] setHidden:YES];
}
}
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
On selection of my cell I'm expanding and reloading the tableview cells.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath==_expandIndexPath) {
_expandIndexPath = nil;
NSMutableArray *modifiedRows = [NSMutableArray array];
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationLeft];
}
else
{
selectedRow=indexPath.row;
NSMutableArray *modifiedRows = [NSMutableArray array];
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
_expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationLeft];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSArray * arr = [filterInfo objectForKey:[orderArray objectAtIndex:indexPath.row]];
if ([indexPath isEqual:_expandIndexPath])
{
if ([[orderArray objectAtIndex:indexPath.row]isEqualToString:#"Height"]||[[orderArray objectAtIndex:indexPath.row]isEqualToString:#"Age"])
{
return 275;
}
else
{
if(arr.count==3)
return 55*arr.count;
else
return 37*arr.count;
}
}
else
return 70;
}
UITableViewCells are getting recycled. That's why its not safe to do it your way. Your data model needs to remember your buttons and other stuff that changed. You need to apply the changes every time the cell gets created.
You need to check in the cellForRowAtIndexPath what button is pressed and then show the view correctly.
You need to remember what happend in the cells with an external data source to apply the changes you want.
In your cellForRowAtIndexPath should be something like a check for a boolean whether or not you show some stuff:
if(button_is_pressed_for_row_5 == true){
button_in_cell.hidden = true;
}else{
button_in_cell.hidden = true;
}
I am using a custom UITableViewCell with a textfield. I want to access each textfield's data when I press on the right navigation bar button (e.g:Done,etc). I am using following code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
#pragma mark - UITableViewDelegate
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomCell *cell = [[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil] objectAtIndex:0];
if (cell == nil) {
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.valueTextField.delegate = self;
switch (indexPath.row) {
case 0:
cell.itemImageView.image = [UIImage imageNamed:#"user.png"];
cell.valueTextField.placeholder = #"UserName";
break;
case 1:
cell.itemImageView.image = [UIImage imageNamed:#"mail.png"];
cell.valueTextField.placeholder = #"Email";
default:
break;
}
Try this
-(IBAction)rightNavigationButton:(id)sender
{
NSInteger rowNumber = [projectListTable numberOfRowsInSection:0];
NSIndexPath *indexpath = [NSIndexPath indexPathForRow:[projectListTable numberOfRowsInSection:0] inSection:0];
for(int i = 0; i < rowNumber; i++)
{
CustomCell *cell = [projectListTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowNumber inSection:0]];
NSString *str = cell.valueTextField.text;
//Do here what you want to do with textfield of each cell
}
}
I solved the issue like this:
-(void)clickOnSend:(id)sender{
NSInteger dynamicRows = [self.createUserTableView numberOfRowsInSection:0];
for (int i=0; i<dynamicRows; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
UserProfileCell *cell = (UserProfileCell *)[self.createUserTableView cellForRowAtIndexPath:indexPath];
DLog(#"cell textfield string :%#",cell.valueTextField.text);
}
}
I am loading a UIWebview in a expand/collapse UITableView. I need to change the row height according to the UIWebview content height. if i set the UIWebview delegate in the UITableview, the UIWebview delgate method keeps get calling over and over. i am calling the webviewDidFinishLoad method to get the content height. Any kind of help/suggestion would be very appreciative.
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.restauRantMenuArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self tableView:self.restaurantMenuTableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return 2; // return rows when expanded
}
return 1; // only top row showing
}
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:self.restaurantMenuTableView canCollapseSection:indexPath.section])
{
if (indexPath.row == 0)
{
static NSString *MyIdentifier = #"menuTitleCell";
RestaurantMenuTitleTableViewCell *cell =(RestaurantMenuTitleTableViewCell*) [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[RestaurantMenuTitleTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RestaurantMenuTitleTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
cell.titleWebView.opaque = NO;
cell.titleWebView.backgroundColor = [UIColor clearColor];
[cell.titleWebView loadHTMLString:object.menuTitle baseURL:nil];
cell.titleWebView.scrollView.scrollEnabled = NO;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
else
{
static NSString *MyIdentifier = #"menuContentCell";
RestaurantMenuContentTableViewCell *cell =(RestaurantMenuContentTableViewCell*) [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[RestaurantMenuContentTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RestaurantMenuContentTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
cell.contentWebView.tag = indexPath.section + 1000;
cell.contentWebView.opaque = NO;
cell.contentWebView.backgroundColor = [UIColor clearColor];
[cell.contentWebView loadHTMLString:object.menuContent baseURL:nil];
//cell.contentWebView.scrollView.delegate = self;
[cell.contentWebView.scrollView setShowsHorizontalScrollIndicator:NO];
// cell.contentWebView.scrollView.scrollEnabled = NO;
//cell.contentWebView.delegate = self;
if([[self.imageHeightArray objectAtIndex:indexPath.section] isEqualToString:#"150"])
{
//cell.contentWebView.delegate = self;
}
// first row
//cell.textLabel.text = #"Expandable"; // only top row showing
if ([expandedSections containsIndex:indexPath.section])
{
//cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
}
else
{
//cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown]
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
return cell;
}
}
else
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor clearColor];
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
UIWebView *thisWebView = (UIWebView*)[self.restaurantMenuTableView viewWithTag:indexPath.section+1000];
[thisWebView loadHTMLString:object.menuContent baseURL:nil];
thisWebView.delegate = self;
//[tableView deselectRowAtIndexPath:indexPath animated:YES];
//if there is any previous selected index
//if selected index is not the previous selected
if (selectedIndex && (selectedIndex.section != indexPath.section)) {
[self collapseOrExpandForIndexPath:selectedIndex inTableView:tableView];
}
if ([selectedIndex isEqual:indexPath]) {
selectedIndex = nil;
}
else{
selectedIndex = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
}
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
[self collapseOrExpandForIndexPath:indexPath inTableView:tableView];
if (indexPath.row == 0) {
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
}
- (void)collapseOrExpandForIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView{
if (!indexPath.row)
{
// only first row toggles exapand/collapse
//[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i
inSection:section];
[tmpArray addObject:tmpIndexPath];
}
if (currentlyExpanded)
{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
}
else
{
//RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
// UIWebView *thisWebView = (UIWebView*)[self.restaurantMenuTableView viewWithTag:indexPath.section+1000];
//
// [thisWebView loadHTMLString:object.menuContent baseURL:nil];
//
// thisWebView.delegate = self;
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return UITableViewAutomaticDimension;
if(indexPath.row == 0)
return 50.00;
else
{
return 240;//[[self.imageHeightArray objectAtIndex:indexPath.section] integerValue];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 1.00;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 1.00;
}
pragma mark Table View Delegate Method ends
Create a class level property (CGFloat),say webViewHeight to track web view's height.
On table view didSelectRowAtIndexPath method load url in web view.
Calculate web view height in webviewDidFinishLoad delegate method of web view and set it in class level height variable,webViewHeight. After calculating height call [tableView reloadData];
Set selected cell height with webViewHeight and rest with default,say 44.0 in heightForRowAtIndexPath method of data source.
IMP: Set maximum web view height also if calculated height exceed max height set calculated height to max height. And enable web view scrolling so that user is able to view all web view content.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"CustomCell";
cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner: self options: nil ];
cell = [nib objectAtIndex:0];
}
//cell.lblName.text = [items objectAtIndex:indexPath.row];
NSMutableDictionary *dic = [items objectAtIndex:indexPath.row];
cell.imgface.image = [dic objectForKey:#"Image"];
cell.imgface.layer.cornerRadius = cell.imgface.frame.size.width / 2;
cell.imgface.layer.borderWidth = 3.0f;
cell.imgface.layer.borderColor = [UIColor whiteColor].CGColor;
cell.imgface.clipsToBounds = YES;
cell.lblName.text = [dic objectForKey:#"Name"];
[cell.btnPhone setTitle:[dic objectForKey:#"Phone"] forState:(UIControlStateNormal)];
cell.btnPhone.tag = indexPath.row;
cell.btnstar.tag = indexPath.row;
[cell.btnPhone addTarget:self action:#selector(dial:) forControlEvents:(UIControlEventTouchUpInside)];
[cell.btnstar addTarget:self action:#selector(toggleimage:) forControlEvents:UIControlEventTouchUpInside];
if (indexPath.section == 0)
{
star = [UIImage imageNamed:#"Star-Favorites.png"];
[cell.btnstar setBackgroundImage:star forState:UIControlStateNormal];
}
else
{
star = [UIImage imageNamed:#"keditbookmarks.png"];
[cell.btnstar setBackgroundImage:star forState:UIControlStateNormal];
}
return cell;
}
write below code in button IBAction and you will get indexpath.row and indexpath.section
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
NSLog(#"selected tableview row is %d",indexPath.row);
You have some different ways to do that:
• When you configure the cell set the tag of the cell or the button as the row and retrieve that on the IBAction (I hate tags though)
• Define a delegate for the table cell and set it when you configure it. Then call the delegate method passing the cell and find the relative index (-indexPathForCell:)
• The same as before but pass the cell through a notification instead of delegates
first of all on, button IBAction call this method
- (IBAction)btnClick:(UIButton)sender
{
UITableViewCell *cellOfcontrol=[self cellWithSubview:sender];
NSIndexPath *indexPath = [self.tableview indexPathForCell:cellOfcontrol];
}
cellWithSubview function
- (UITableViewCell *)cellWithSubview:(UIView *)subview
{
while (subview && ![subview isKindOfClass:[UITableViewCell self]])
subview = subview.superview;
return (UITableViewCell *)subview;
}
I am using Custom Cell for UITableView and there is a UIButton on it which should remove the current cell from the table view.
In cellForRowAtIndexPath I am doing
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellIdentifier";
NSLog(#"Creating Cell");
FADynamicCell *cell= (FADynamicCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([FADynamicCell class])
owner:nil
options:nil] lastObject];
}
currentIndexPath = indexPath;
UIButton *removeButton = [UIButton buttonWithType:UIButtonTypeCustom];
removeButton.tag = indexPath.row +100;
removeButton.frame = cell.removeButton.frame;
removeButton.backgroundColor = [UIColor colorWithRed:255./255 green:65./255 blue: 21./255 alpha:1];
removeButton.titleLabel.font = [UIFont systemFontOfSize:12];
removeButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[removeButton setTitle:#"Remove" forState:UIControlStateNormal];
[removeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[removeButton addTarget:self action:#selector(removing) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:removeButton];
return cell;
}
And in Function for removing
-(void) removing
{
[TOperations deleteTickerFromGroup:tickerGroupID andTickerSymbol:selectedSymbol];
NSNumber *selectedRowIndex1 = [NSNumber numberWithInteger:currentIndexPath.row];
[tableView1 beginUpdates];
NSIndexPath *previousPath = [NSIndexPath indexPathForRow:selectedRowIndex1.integerValue-1 inSection:0];
[tableView1 endUpdates];
[tableView1 reloadData];
}
Now problem is that it is showing animation on the correct cell but I am not able to remove the custom cell from the table view. And whenever I load the view again i.e. comes from other screen it does not shows the cell on which I have clicked for removing.
Any help will be appreciated...
To delete a row/cell from table view, you need to call the deleteRowsAtIndexPaths:withRowAnimation: method on your UITableView instance.
NSIndexPath *previousPath = [NSIndexPath indexPathForRow:selectedRowIndex1.integerValue-1 inSection:0];
[self.yourTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:previousPath] withRowAnimation:UITableViewRowAnimationFade];
This will update the UI, but remember to remove that row from your data source as well. This will ensure it is deleted completely.
Hope that helps!