EDITED CODE..
Hello frds, i have one buttom in UIScrollview when i clicked on that button then i get btn.tag , so after that i want to scroll UITableView programatically.
Here is my Code.
//-- Custom Scrollview--//
- (void)loadscrollViews
{
int a =[DBConnection rowCountForTable:#"DD_Pic_Tags_Comments" where:[NSString stringWithFormat:#"img_Moment_id=%#",STR_Select_moment_id_for_timelinepage2]];
numofimageinscrollview=a;
int x=0;
for (int i = 0; i < a; i++)
{
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame=CGRectMake(x, 0,scrollView.frame.size.height,scrollView.frame.size.height);
btn.tag=i;
UIImage *image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#.jpg",Pathforimage,[[Array_result objectAtIndex:i] objectForKey:#"img_File_Name"]]];
[btn setImage:image forState:UIControlStateNormal];
[btn addTarget:self action:#selector(imageClick:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:btn];
scrollView.contentSize=CGSizeMake((i+2)*scrollView.frame.size.height,scrollView.frame.size.height);
x+=scrollView.frame.size.height+5;
}
}
-(void)imageClick:(id)sender
{
UIButton *btn=(UIButton *)sender; //UIScrollView Button
int count = (int)btn.tag;
NSLog(#"click on small image in Scrollview>> count = %d",count);
NSIndexPath *indexpath=[NSIndexPath indexPathForRow:count inSection:0]; //Set Count For RoW
NSLog(#"%d %d",indexpath.row,indexpath.section);
[self.Table reloadData];
[self.Table scrollToRowAtIndexPath:indexpath
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}
Get Error like,
2014-08-25 16:34:27.757 Omoment[5163:60b] click on small image in Scrollview>> count = 2
2014-08-25 16:34:27.758 Omoment[5163:60b] 2 0
2014-08-25 16:34:27.761 Omoment[5163:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]: row (2) beyond bounds (0) for section (0).'
*** First throw call stack:
libc++abi.dylib: terminating with uncaught exception of type NSException
but,
app crash , but when i set NSIndexPath *indexpath=[NSIndexPath indexPathForRow:1 inSection:0];
//at that time app does not crash, & there is no output in uitableview, & also scrollview did not scroll also..
I think you have not defined the tag for that image in cellforrowatindexpath. I have used a button instead of image.I hope it works for u.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:simpleTableIdentifier owner:self options:nil] objectAtIndex:0];
}
cell.txtlabel.text = [NSString stringWithFormat:#"Hello %d", indexPath.row];
[cell.btnnn addTarget:self action:#selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];
cell.btnnn.tag=indexPath.row;
return cell;
}
-(void)btnPressed:(id)sender{
UIButton *btn=(UIButton *)sender; //UIScrollView Button
int count = (int)btn.tag;
NSLog(#"click on small image in Scrollview>> count = %d",count);
NSIndexPath *indexpath=[NSIndexPath indexPathForRow:count inSection:0]; //Set Count For RoW
NSLog(#"%d %d",indexpath.row,indexpath.section);
// [self.tbl reloadData];
[self.tbl scrollToRowAtIndexPath:indexpath
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}
You need to scroll the Scrollview.
For this first calculate the CGPoint up to which you need to scroll.
Then use this:
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
So your final code would be something like this:
-(void)btnPressed:(id)sender{
UIButton *btn=(UIButton *)sender; //UIScrollView Button
CGFloat y_point = btn.center.y; // Adjust the y point according to you
CGPoint thePoint = CGPointMake(0, y_point); // Assuming its a vertical scroll
[self.myScroll setContentOffset:thePoint animated:YES];
}
Related
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!
-(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 trying to reach button indexpath in a correctly filled UITableView. I have two labels and one button in every cell customized in anouther XIB. When I click the button in any row in any section, it returns mw wrong indexpath. I am wondering what may cause this. Below you can find my code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ProgramCell";
ProgramCell *cell = (ProgramCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ProgramCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.contentView setUserInteractionEnabled: NO]; //
NSString* strTemp = [NSString stringWithFormat: #"%d/%d", indexPath.section, indexPath.row ];
for (int i = 0; i < buttonClickedArray.count; i++) {
if([[buttonClickedArray objectAtIndex:i] isEqualToString:strTemp])
{
[cell.btnHatirlat setBackgroundColor:[UIColor colorWithRed:0.0 green:0.5 blue:0. alpha:0.7]];
[cell.btnHatirlat setTitle:#"Eklendi" forState:UIControlStateNormal];
}
}
NSString *str = #"";
str = [arrayPazartesi objectAtIndex:indexPath.row];
if ([str length] > 1)
{
NSString *strSaat = [str substringToIndex:5];
NSString *strEtkinlikAdi = [str substringFromIndex:6];
cell.lblEtkinlik.text = strEtkinlikAdi;
cell.lblSaat.text = strSaat;
[cell.btnHatirlat addTarget:self action:#selector(hatirlat:)
forControlEvents:UIControlEventTouchUpInside ];
}
return cell;
}
- (void) hatirlat:(UIButton *)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableProgram];
NSIndexPath *indexPath = [self.tableProgram indexPathForRowAtPoint:buttonPosition];
int j = indexPath.section; //true section
int i = indexPath.row; //wrong row
}
I've seen this problem before (but can't find the reference), and the fix was to not pick the corner of the button (I think this would only be a problem if the button is right at the top of a cell). Instead of,
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableProgram];
Try this to make sure you're not right on an edge,
CGPoint boundsCenter = CGRectOffset(sender.bounds, sender.frame.size.width/2, sender.frame.size.height/2).origin;
CGPoint buttonPosition = [sender convertPoint:boundsCenter toView:self.tableView];
Try using this instead. I have seen quite a few people complain about this method behaving quite weirdly.
CGPoint point = [self.tableView convertPoint:sender.frame.origin fromView:sender.superview];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
Edit
The preferred way to do this would be to have the cell create the button (maybe during the init). And define a protocol for this cell, that returns a reference to the cell. Set the cell as the button delegate and when the button is clicked, pass a reference to the cell back to the cell delegate, which can call
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
e.g.
UITableViewCell.h
#protocol MyCellDelegate <NSObject>
#optional
- (void)cell:(UITableViewCell *)cell buttonPressed:(UIButton *)button;
#end
#interface MyCell : UITableViewCell
#property (weak, nonatomic) id<MyCellDelegate> delegate;
UITableViewCell.m
- (void)setDataWithDictionary:(NSDictionary *)dictionary
{
[self.titleLbl setText:[dictionary objectForKey:#"title"]];
[self.amountLbl setText:[dictionary objectForKey:#"amount"]];
btn = [[UIButton alloc] init];
[btn addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
.....
}
- (void)buttonPressed
{
if(self.delegate)
{
if([self.delegate respondsToSelector:#selector(cell:buttonPressed:)])
{
[self.delegate cell:self buttonPressed:btn];
}
}
}
Why don't you set the elements index inside the UIButtons tag inside cellForRowAtIndexPath ?
Everytime you push the UIButton hatirlat will be called and you can access the index by the sender.
Maybe it will cause a problem because of your two UITableViews but I don't know exactly your code.
- (void) hatirlat:(UIButton *)sender{
UIButton *button = (UIButton *)sender;
_arrayForPosition[button.tag];
}
The button action is SongsSelectionSongs_Click. When I click this button, the button image changing, the button tap count is getting correct and after selected button images also changing, but when I scroll back and forth in the UITableView the button image seems to be randomly changing.
This is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"SongsTAbleViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SongsTAbleViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
btn_songSelect.tag = indexPath.row;
lbl_songLabel.text = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongTitle"];
lbl_artistLabel.text = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongArtist"];
return cell;
}
-(IBAction)SongsSelectionSongs_Click:(id)sender
{
UIButton *button = sender;
CGPoint correctedPoint = [button convertPoint:button.bounds.origin toView:self.tblv_SongslisttableView];
NSIndexPath *indexPath = [self.tblv_SongslisttableView indexPathForRowAtPoint:correctedPoint];
NSLog(#"Button tapped in row %d",indexPath.row);
SelectedAlbumUrl = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongUrl"];
str_songtitle = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongTitle"];
if ([[button backgroundImageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"add.png"]])
{
btn_songsShareButton.userInteractionEnabled = YES;
[btn_songSelect setBackgroundImage:[UIImage imageNamed:#"remove.png"] forState:UIControlStateNormal];
buttonStatus = buttonStatus +1;
[btn_songsShareButton setImage:[UIImage imageNamed:#"share selected.png"] forState:UIControlStateNormal];
}
else
{
[btn_songSelect setBackgroundImage:[UIImage imageNamed:#"add.png"] forState:UIControlStateNormal];
buttonStatus = 1;
[btn_songsShareButton setImage:[UIImage imageNamed:#"share unselected.png"] forState:UIControlStateNormal];
}
}
You are not doing anything within your cellForRowAtIndexPath to select or deselect image. When you reuse a cell, it doesn't change the state of the cell unless you explicitly tell it to in cellForRow. Therefore, it will either reuse a selected or deselected cell (whatever is the first available reusable cell) and put that on the screen as-is.
To fix this issue, you need logic in your cellForRowAtIndexPath method to either select or deselect the image based on what is appropriate.
In general, if your problem has anything to do with "my cells don't show up right when scrolling" odds are you're not reusing your cells properly.
EDIT: in response to your comment, no, I will not rewrite your code. But I will give you some direction.
I would recommend keeping an additional key/value on your arr_tablVArray that will track whether or not the "share" should be enabled or disabled (I would suggest a bool value). This would make it so that you could check whether or not the "share" is enabled/disabled by checking a bool instead of checking the contents of the button's image in your IBAction method.
This info would now be available in your cellForRowAtIndexPath method as well, and you could check the value for the current record in arr_tablVArray and set your images accordingly just like you set your lbl_songLabel and lbl_artistLabel.
//Try It, it's Working Fine
pragma .h File
NSMutableArray * rowIdArray;
pragma .M File
#synthesize rowIdArray;
- (void)viewDidLoad
{
rowIdArray=[[NSMutableArray alloc]init];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [NamesArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
ViewControllerCell *cell = (ViewControllerCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
NSArray *nib;
nib = [[NSBundle mainBundle] loadNibNamed:#"ViewControllerCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// Configure the cell...
cell.nameslbl.text = [NamesArray objectAtIndex:indexPath.row];
cell.nameBtn.tag=indexPath.row;
[cell.nameBtn addTarget:self action:#selector(NamesClick_Tapped:) forControlEvents:UIControlEventTouchUpInside];
NSString *a=[NSString stringWithFormat:#"%d", indexPath.row];
NSString *b=[[NSString alloc]init];
for (int i=0;i<[rowIdArray count];i++)
{
b=[rowIdArray objectAtIndex:i];
if ([a isEqualToString:b])
{
UIImage *buttonImage = [UIImage imageNamed:#"star_selected.png"];
[cell.nameBtn setBackgroundImage:buttonImage forState:UIControlStateNormal];
}
}
return cell;
}
-(IBAction)NamesClick_Tapped:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.NameTableView];
NSIndexPath *indexPath = [self.NameTableView indexPathForRowAtPoint:buttonPosition];
NSString *rowIdStr = [NSString stringWithFormat:#"%d", indexPath.row];
if(![rowIdArray containsObject:rowIdStr])
{
[rowIdArray addObject:rowIdStr];
}else{
[rowIdArray removeObject: rowIdStr];
}
[self.NameTableView reloadData];
}
when you reuse a cell where the button has been already set, the same button appears with the previously set image. Instead of creating a new button every time you need a cell, you should just be resetting the state of an existing button. This link might help you.
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!