uitableview drag and drop with not moving cells - ios

I would like to make use of the drag and drop reordering of tableview cells, but I have one problem:
I would like to keep my first row in place!
Here is the canMoveRowAtIndexPath delegate function:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row==0) {
return NO;
}
return YES;
}
If I do it like this, the first row can not be dragged, BUT you can still drag another row on top of it! Is there any way to prevent cells from dropping 'above' this row?

Your answer is hear,
You can use these step.
Examples of Moving a Row

check if it is a drag and cancel the scrolling if it is = [uitableview setScrollEnabled:NO]
read this thread, it will help you i hope
Tutorial on How to drag and drop item from UITableView to UITableView

Related

iOS - Swipe to delete while also allowing moving rows

My table view is in editing mode allowing my cells to be moved around. Is it possible to also add swipe to delete, NOT using the red-circle-delete button.
I want to be able to show just the move cell image, allowing moving, and also have a swipe to delete.
Is this possible?
This is what I currently have going on.
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return UITableViewCellEditingStyleDelete;
}
else
return UITableViewCellEditingStyleNone;
}
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1)
return YES;
else
return NO;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
It is definitely possible, though not as simple as you'd probably like. There are three parts to this:
The "swipe" gesture
The UI animation
The delete action
The "swipe" gesture should probably not be a UISwipeGestureRecognizer. UIPanGestureRecognizer will update as the user moves their finger around and matches what the user expects.
The animation should have two parts: update and complete. Update should simply pan the cell view inside of the cell to follow along with the user's finger. Once the gesture has reached a point of "completion" then animate the cell view going off screen.
Lastly, the delete action should be familiar if you've used the UITableViewDelegate methods. If not, here's a link to a helpful answer on the subject.
I would actually implement these out of order. First, programmatically test deleting a row. When that works, add an UIPanGestureRecognizer to call the delete row. Then move the cell view around with the pan gesture. Finally, animate the completion of the cell view moving around.

How to avoid tap on accessory button in table view cell when selection is not allowed?

I have my table view that displays cells with some content and a custom accessory button.
When i tap a cell, a 5s work is launched. I don't want the user to tap a cell while the background work is not finished, so i do:
self.tableView.allowsSelection = NO;
It works fine, the user can't tap a cell.
I used to do:
self.tableView.userInteractionEnabled = NO;
But i want to scroll my table view while working in background. The issue is that i also can tap on the cell's accessory button.
How to avoid that not losing the table view scroll?
I could do:
- (void)didSelectAccessoryButton:(UIButton *)pButton onEvent:(id)event{
if(self.tableView.allowsSelection){
//Usual accessory button code
}
}
But the accessory button highlight would still be there, meaning at some point i'd need to do in cellForRowAtIndexPath:
[accessoryButton setShowsTouchWhenHighlighted:NO];
I just wish the allowsSelection = NO avoids the tap on accessory button too... So what's the better way ?
The best way i've found is to combine this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//...
tableView.allowsSelection = NO;
[tableView reloadData];
//...
}
with this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//...
accessoryButton.userInteractionEnabled = tableView.allowsSelection;
//or cell.accessoryView.userInteractionEnabled = tableView.allowsSelection;
//
}
And when the job is done, self.tableView.allowsSelection = YES;.
What bothers me with this solution is the need to check inside cellForRowAtIndexPath as to do so i also need to reload data; but in the end it's just 3 lines.
Thank you #virus for the simple "userInteractionEnabled to accessoryButton" idea.

UITableView - how to recognize if i drag a cell over a cell?

I want to recognize when i select a cell and drag it over another cell.
Is there any example/ workaround for this?
My goal is to create an UITableView which allows me to merge two cells into one cell.
Thanks
You can use UITableView delegates
to move rows
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
And To compare CGRects
self.tableView rectForRowAtIndexPath:(NSIndexPath *)
Then, I believe, create, insert new cell.

Manage Swapping between two cells rather than changing the NSIndexpath of other UITableViewcells

I know it's the default property of rearrangement of tableviewcells when UITableView is in editing mode & user just reorder the Rows which is handled by UITableViewController.
As per Apple Doc : Reordering of Rows
Now what I want to do is, when I drag the cell over other cells, the backend cells should not get rearranged automatically, just the cell on which I drop the dragged cell should gets rearranged, a kind of Swapping between two cells.
For better understanding, please refer the below image. I should be able to Shift Jones to Room1 & the tableview controller should able to automatically be shifting Smith2 to Room3.
Below are delegates methods which I am using :
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
NSString *temp = [roomstoringArray objectAtIndex:sourceIndexPath.row];
[roomstoringArray removeObjectAtIndex:sourceIndexPath.row];
[roomstoringArray insertObject:temp atIndex:destinationIndexPath.row];
// [temp release];
}
Problem is :
How can I stop other cells to get rearranged automatically while I
am dragging the cells over other.
There none of the delegate method which gets called when one used to
Drag the cell over others, only method called is
moveRowAtIndexPath when one drop the cell on it. So, even can't check for some condition & didn't find any scope of this enhancement
within existing TableView.
Is there any property with the TableView where I can stop such kind of behavior to perform the swapping between two cells only where rest of rows remain at the same indexPath.Alos, can someone please help me out with some-other way,if any.
For Problem you mention, Please check UITableView Delegates from here.
Below methods are helpful to you.
targetIndexPathForMoveFromRowAtIndexPath
canMoveRowAtIndexPath
For Swap b/w two rows you can get idea by this answer.

Want to expand and collapse UITableview Section

I want to expand UITableView section where I have to show UITableViewCells. What should I do to achieve this?
A simple implementation would be keep your cell height as zero for
sections.
Make the viewForSectionHeader touchable
When you touch it, set proper height for cells under the section
Write a logic for switching between sections
OR,
On touching the section header reload the table with updated rows count for section touched.
Many other ways to do it. Apple example.
According to Vignesh's answer, I have tried the second solution."On touching the section header reload the table with updated rows count for section touched."
First, declare an array to store the isExpanded tag for each section.Initial, all value is BOOL NO.Means all the section rows are collapsed.
Then, in the
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
method, implement the sectionHeader touch event by following code:
Because I use a custom cell as section header view. so here is the "cell",you can use your own view.
cell.tag=section;
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(sectionTapped:)];
[cell addGestureRecognizer:recognizer];
cell.userInteractionEnabled=YES;
And, do something when the sectionHeader is tapped.
- (void)sectionTapped:(UITapGestureRecognizer *)recognizer
{
NSMutableArray *isSectionTouched=[[NSMutableArray alloc]initWithCapacity:_sectionExpandBool.count];
isSectionTouched=[_sectionExpandBool mutableCopy];
if ([[isSectionTouched objectAtIndex:recognizer.view.tag]boolValue]==YES) {
[isSectionTouched replaceObjectAtIndex:recognizer.view.tag withObject:[NSNumber numberWithBool:NO]];
}else if ([[isSectionTouched objectAtIndex:recognizer.view.tag]boolValue]==NO){
[isSectionTouched replaceObjectAtIndex:recognizer.view.tag withObject:[NSNumber numberWithBool:YES]];
}
_sectionExpandBool=isSectionTouched;
[self.tableView reloadData];
}
Don't forget to modify the numberOfRowsInSection method. The row.count should change according the value of _sectionExpandBool, if the section's ExpandBool is YES, should return the correct number of your datasource,else return 0.
It works as my expectation. However, I'm a little worried about the memory leak or something, because every time tap the header, the whole table view will reload again.
I wonder if there is some solution for only reload the specific section. Thanks.

Resources