I have uitableview and it has 1 button "TOP" in each row. I want to when user click on this button, this row has been push on top in Uitableview ( with animation). Can i reuse BVReorderTableView to do that? How can i do that? Thanks much
i am assuming your -cellForRowAtIndexPath loads cell contents from an array such as the one i named arrObjects which:
is an NSMutableArray object
has many NSString objects
something like:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//...
[cell.textLabel setText:[arrObjects objectAtIndex:indexPath.row]];
UIButton *btnUp = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnUp setFrame:CGRectMake(0, 0, 30, 30)];
//[btnUp setTag:100];
[btnUp setTitle:#"\u261D" forState:UIControlStateNormal];
[btnUp addTarget:self
action:#selector(moveToTop:)
forControlEvents:UIControlEventTouchUpInside];
[cell setAccessoryView:btnUp];
return cell;
}
- (void)moveToTop:(UIButton *)sender
{
UITableViewCell *cell = (UITableViewCell *)sender.superview; //iOS6 prior
//UITableViewCell *cell = (UITableViewCell *)sender.superview.superview; //iOS7
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//uncomment lines for safety, incase indexPath ever comes nil... prevent the crash
//if (indexPath == nil) {
// return;
//}
//1. move and animate row to top
[self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row
inSection:indexPath.section]
toIndexPath:[NSIndexPath indexPathForItem:0
inSection:indexPath.section]];
//2. make appropriate changes to the datasource
//so that it reflects logically and is not just an aestehtical change
//PRE-NOTE:
//arrObjects is an object of a category on NSMutableArray
//with a custom instance method named -moveObjectFromIndexPath:toIndex:
//uncomment the following line when you are ready with the category
//[arrObjects moveObjectFromIndex:indexPath.row toIndex:0];
}
the category is easy to create, follow:
http://www.icab.de/blog/2009/11/15/moving-objects-within-an-nsmutablearray/
other links to try:
http://adeem.me/blog/2009/05/29/iphone-sdk-tutorial-add-delete-reorder-uitableview-row/
http://learn-iphone-app-development.com/2011/01/31/tables-part-iii-%E2%80%94-re-ordering-moving-cells-and-swipe-to-delete/
have you tried
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
you can use animations if you want so..
You can easy do that like this:
[self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
or:
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
or:
[self.tableView scrollRectToVisible:CGRectMake(0.f, 0.f, CGRectGetWidth(self.tableView.frame), CGRectGetHeight(self.tableView.frame)) animated:YES];
Edit
Sorry, I misunderstood what you meant.
You should do that like this:
[tableView moveRowAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
If you want to tableView scroll to the top immediately after move the cell, you can try the above code.
Edit
// A more detailed description
- (void)buttonHandle:(UIButton *)sender {
// Assuming button is added directly on the cell.
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
[tableView moveRowAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}
Related
I have a tableview. It will receive mess of data from server. Every time tableview receive data I wanna it show the latest one at bottom.I called scrollToRowAtIndexPath:atScrollPosition:animated: but it lag my app i can do nothing else in my screen when scroll to bottom of tableview.
Here is my main code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"tableViewCell";
DLtestCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
NSDictionary* dict = arr[indexPath.row];
cell.myLabel.attributedText = dict[#"content"];
[cell.myImageview sd_setImageWithURL:dict[#"imageUrl"] placeholderImage:[UIImage imageNamed:#"transparentPlaceHolder"]];
return cell;
}
and here is scrolling to the bottom main code
- (void)reloadTableView
{
dispatch_async(dispatch_get_main_queue(), ^{
NSIndexPath *lastRow = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView insertRowsAtIndexPaths:#[lastRow] withRowAnimation:UITableViewRowAnimationLeft];
});
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}
You should use scrollToRowAtIndexPath method.
And in viewWillAppear write below code.
[theTableView reloadData];
NSIndexPath* ip = [NSIndexPath indexPathForRow:rowNumber inSection:sectionNumberHere];
[theTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO];
here 'rowNumber' is the row number in the data source you want to scroll to.
or you can calculate 'rowNumber' as follows:
int lastRowNumber = [tableView numberOfRowsInSection:0] - 1;
and pass this lastRowNumber to indexPathForRow.
NOTE : numberOfRowsInSection returns row count, not the last row number (which is row count - 1).
In my UITableView "tableview" I added checkboxes in each row using UITableView default functionality.
- (void)viewDidLoad {
[tableview setEditing:YES animated:YES];
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 3;
}
I can select only Multiple checkboxes.But I want to select all the checkboxes using a button click.I can use didSelectRowAtIndexPath to loop through all the rows and get the contents but the checkboxes stays unchecked.
- (IBAction)selectallbutton:(id)sender {
NSInteger nRows=[arr count];
for(int i=0;i<nRows;i++){
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[self tableView:tableview didSelectRowAtIndexPath:indexPath];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",[arr objectAtIndex:indexPath.row]);
}
Is it possible to check them all using this approach or should I try another way?
try this,
- (IBAction)selectallbutton:(id)sender {
NSInteger nRows=[arr count];
for(int i=0;i<nRows;i++){
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
UITableViewCell *cell = [tableview cellForRowAtIndexPath:indexPath];
[cell setSelected:YES animated:NO]; //you can change animated:YES if needed
}
}
Here is my code. And yesterday it works just fine. But this morning, it doesn't work.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
RSDrug *drug = [[RSDrug alloc]init];
[drugArray insertObject:drug atIndex:0];
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 inSection:0];
[tableView insertRowsAtIndexPaths:#[ip] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return drugArray.count + 1;
}
I have tried to add some code like beginUpdates/endUpdates, or I delete insertRowsAtIndexPaths, just use reloadData.
But same result. When the app runs to insertRowsAtIndexPaths or reloadData, it stuck, no response.
So I need some help. How to solve this?
Found the problem..........A stupid mistake
There are two UITextFields in the added cell, and they all have the same leftView, my code is like this:
UIImageView *leftImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"img"]];
field_1.leftView = leftImage;
field_2.leftView = leftImage;
I never know that I can't reuse the leftView. If I set the leftImage to field1, I can't set it to field2 anymore.
When I changed to this, it works again.
field_1.leftView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"img"]];
field_2.leftView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"img"]];
Try this sequence...
NSMutableArray *indexPaths=[[NSMutableArray alloc]init];
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView beginUpdates];
RSDrug *drug = [[RSDrug alloc]init];
[drugArray insertObject:drug atIndex:0];
if (indexPath.row == 0) {
[indexPaths removeAllObjects];
[indexPaths addObject:[NSIndexPath indexPathForRow:indexPath.row++ inSection:0]]; // here inserting row index=1;
[tableViewMenuList insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
}
[tableView endUpdates];
}
Have you tried this?
RSDrug *drug = [[RSDrug alloc]init];
[drugArray insertObject:drug atIndex:0];
[tableView beginUpdates];
// indexpath inserted is with the index 0 same with the `insertObject: `
NSIndexPath *ip = [NSIndexPath indexPathForRow:0 inSection:0];
[tableView insertRowsAtIndexPaths:#[ip] withRowAnimation:UITableViewRowAnimationAutomatic];
//here is what i use to do instead of #[]
//[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
EDIT
Your code are working fine. i tested it. here..
Code:
Output:
Log:
Check the tested code above if you have omitted something.
I think the problem is the delegates of your table, make sure that your table have the delegate for both UITableViewDataSource & UITableViewDelegate.
Hope this is helpful.. Cheers.. :)
I would like to make something like expandable cells. Result I'm trying to achieve is:
Actually I have:
Here is my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
DoctorCell *cell = self.prototypeCell;
DoctorModel *doctor = [self.fetchController objectAtIndexPath:frcIndexPath];
// depending on isActive property I add (or do not add) some content.
[cell cellForDoctor:doctor isActiveCell:[self.activeCellIndexPath isEqual:indexPath]];
[cell setNeedsUpdateConstraints];
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height + 1;
}
Here is my cell selection method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSIndexPath *oldIndexPath = self.activeCellIndexPath;
if ([indexPath isEqual:self.activeCellIndexPath]) {
self.activeCellIndexPath = nil;
oldIndexPath = nil;
} else {
self.activeCellIndexPath = indexPath;
}
[self.doctorTableView beginUpdates];
[self.doctorTableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, oldIndexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.doctorTableView endUpdates];
[self.doctorTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
As you can see, my animation looks weird (kind of moving to wrong position, jumps, etc). What I'm doing wrong? Or do I need to pick another approach for expanding cells?
You can use UITableViews animation automation like this:
Call [tableView beginUpdates];
Change the data source.
Insert or delete rows and sections, or reload them
This should cause new heights to be calculated, etc.
Make sure you use something appropriate for the withRowAnimation parameter of these methods
Call [tableView endUpdates];
Your animation should now perform as expected.
Maybe your problem is that you selected UITableViewRowAnimationNone for the row animation.
I am using a tableView which loads a custom UITableViewCell with a "Tap" button inside it. A method is called when user clicks the button.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{...
[btnRowTap addTarget:self action:#selector(didButtonTouchUpInside:) forControlEvents:UIControlEventTouchDown];
...
return cell;
}
In the didButtonTouchUpInside method, Im trying to retrieve the value of row selected in the following way:
-(IBAction)didButtonTouchUpInside:(id)sender{
UIButton *btn = (UIButton *) sender;
UITableViewCell *cell = (UITableViewCell *)btn.superview;
NSIndexPath *indexPath = [matchingCustTable indexPathForCell:cell];
NSLog(#"%d",indexPath.row);
}
The problem is that on clicking button at any row, I am getting the same value of 0 every time.
Where am I going wrong?
You must NOT rely on the view hierarchy of a UITableViewCell. This approach will fail in iOS7, because iOS7 changes the view hierarchy of the cell. There will be an additional view between your button and the UITableViewCell.
There are better ways to handle this.
Convert the button frame so it is relative to the tableview
ask the tableView for the indexPath at the origin of the new frame
.
-(IBAction)didButtonTouchUpInside:(id)sender{
UIButton *btn = (UIButton *) sender;
CGRect buttonFrameInTableView = [btn convertRect:btn.bounds toView:matchingCustTable];
NSIndexPath *indexPath = [matchingCustTable indexPathForRowAtPoint:buttonFrameInTableView.origin];
NSLog(#"%d",indexPath.row);
}
set Button tag in to cellForRowAtIndexPath method Befor setting Method like
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{...
btnRowTap.tag=indexPath.row
[btnRowTap addTarget:self action:#selector(didButtonTouchUpInside:) forControlEvents:UIControlEventTouchDown];
...
return cell;
}
and your tapped cell getting like this:-
-(IBAction)didButtonTouchUpInside:(id)sender{
{
UIButton *button = (UIButton*)sender;
NSIndexPath *indPath = [NSIndexPath indexPathForRow:button.tag inSection:0];
//Type cast it to CustomCell
UITableViewCell *cell = (UITableViewCell*)[tblView1 cellForRowAtIndexPath:indPath];
NSLog(#"%d",indPath.row);
}
try like this,if you are adding button to cell content view then use below code.
UITableViewCell *buttonCell = (UITableViewCell *)sender.superview.superview;
UITableView* table1 = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table1 indexPathForCell:buttonCell];
int rowOfTheCell = [pathOfTheCell row];
int sectionOfTheCell = [pathOfTheCell section];
btn.superview is contentView of UITableviewCell. Use btn.superview.superview instead.
if you already knew the value inside the cell, then
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *currentCell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if ([currentCell.textLabel.text isEqualToString:#"Your Cell Text value" ]){
//Do theStuff here
}
}
here is the code for your ibAction.you dont need to set any tag or anything else
-(IBAction)didButtonTouchUpInside:(id)sender{
NSIndexPath *indexPath =
[tbl
indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
}