简体   繁体   中英

How to drag UITableViewCell and drop it to another UITableView?

I was able to get only partial output, main functionality of drag and drop was achieved but it was crashing some times and showing error as index out of bounds.

I use pan gesture controller to drag and drop the UITableView cell, I also want to know how it can be done by using touches began,touches moved and touches ended method.

This is my sample code

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    pathNumber=indexPath.row;
    cell = [tableView cellForRowAtIndexPath:indexPath];
    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDetected:)];
    [cell addGestureRecognizer:panRecognizer];


    if (cell.accessoryType==UITableViewCellAccessoryNone)
    {

        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        if(tableView==tableView1)
        {
            [selectedCells addObject:[array objectAtIndex:indexPath.row]];
            NSLog(@"indexpath-%d",indexPath.row);
            [arrayOfPaths addObject:indexPath];
            NSLog(@"----%@",selectedCells);
            NSLog(@"----======%@",arrayOfPaths);
        }
        else
        {
            [selectedCells1 addObject:[array1 objectAtIndex:indexPath.row]];
            NSLog(@"indexpath-%d",indexPath.row);
            [arrayOfPaths1 addObject:indexPath];
            NSLog(@"====%@",selectedCells1);
            NSLog(@"----======]]]]]%@",arrayOfPaths1);
        }
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
        if(tableView==tableView1)
        {
            [selectedCells removeObject:[array objectAtIndex:indexPath.row]];
            [arrayOfPaths removeObject:indexPath];
            NSLog(@"----%@",selectedCells);
            NSLog(@"----======remove%@",arrayOfPaths);
        }
        else
        {
            [selectedCells1 removeObject:[array1 objectAtIndex:indexPath.row]];
            [arrayOfPaths1 removeObject:indexPath];
            NSLog(@"====%@",selectedCells1);
            NSLog(@"----======remove1%@",arrayOfPaths1);
        }
    }
}

- (void)panDetected:(UIPanGestureRecognizer *)panRecognizer
{
    CGPoint translation = [panRecognizer translationInView:self.view];
    CGPoint cellViewPosition = cell.center;
    cellViewPosition.x += translation.x;
    cellViewPosition.y += translation.y;

    cell.center = cellViewPosition;
    [self.view bringSubviewToFront:cell];
    [panRecognizer setTranslation:CGPointZero inView:self.view];
    NSArray * arr=[NSArray arrayWithObject:[NSIndexPath indexPathForRow:pathNumber inSection:0]];
    NSArray * arr1=[NSArray arrayWithObject:[NSIndexPath indexPathForRow:pathNumber inSection:0]];

    if(panRecognizer.state==UIGestureRecognizerStateBegan)
    {
        position1=[panRecognizer locationInView:self.view];
    }
    if(panRecognizer.state==UIGestureRecognizerStateEnded)
    {
        position = [panRecognizer locationInView:self.view];

        NSLog(@"%f %f",position.x,position.y);

        if(CGRectContainsPoint(tableView2.frame, position))
        {
            NSLog(@"1-2");
            if(position.x>=tableView2.frame.origin.x && position1.x >= tableView1.frame.origin.x  && position1.x <= tableView1.frame.size.width)
            {
                if([selectedCells count] ==1)
                {
                    [tableView2 beginUpdates];
                    [tableView2 insertRowsAtIndexPaths:arr1 withRowAnimation:UITableViewRowAnimationTop];
                    [array1 insertObject:[array objectAtIndex:pathNumber] atIndex:pathNumber];
                    d=[array1 count];
                    [tableView2 endUpdates];

                    [tableView1 beginUpdates];
                    [tableView1 deleteRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationTop];
                    [array removeObjectAtIndex:pathNumber];
                    c=[array count];
                    [tableView1 endUpdates];
                }
                else
                {
                    [tableView2 beginUpdates];
                    [tableView2 insertRowsAtIndexPaths:arrayOfPaths withRowAnimation:UITableViewRowAnimationTop];
                    for(int j=0;j<[arrayOfPaths count];j++)
                    {
                        NSIndexPath * tempIndexPath = (NSIndexPath *)([arrayOfPaths objectAtIndex:j]);
                        [array1 insertObject:[selectedCells objectAtIndex:j] atIndex:tempIndexPath.row];
                    }
                    d=[array1 count];
                    NSLog(@"%d", d);
                    [tableView2 endUpdates];

                    [tableView1 beginUpdates];

                    [tableView1 deleteRowsAtIndexPaths:arrayOfPaths withRowAnimation:UITableViewRowAnimationTop];
                    for(int j = 0;j < [arrayOfPaths count]; j++)
                    {
                        NSIndexPath * temp = (NSIndexPath *)[arrayOfPaths objectAtIndex:j];
                        [array removeObjectAtIndex:temp.row];
                    }
                    c=[array count];
                    [tableView1 endUpdates];


                }
                [selectedCells removeAllObjects];
                [arrayOfPaths removeAllObjects];
            }
            else
            {
                NSLog(@"else");
            }

        }

        else if(CGRectContainsPoint(tableView1.frame, position))
        {
            NSLog(@"hi-2");
            if(position.x>=tableView1.frame.origin.x && position1.x >= tableView2.frame.origin.x  && position1.x <= tableView2.frame.size.width + tableView2.frame.origin.x)
            {
                if([selectedCells1 count] == 1)
                {
                    [tableView1 beginUpdates];
                    [tableView1 insertRowsAtIndexPaths:arr1 withRowAnimation:UITableViewRowAnimationTop];
                    [array insertObject:[array1 objectAtIndex:pathNumber] atIndex:pathNumber];
                    c=[array count];
                    [tableView1 endUpdates];

                    [tableView2 beginUpdates];
                    [tableView2 deleteRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationTop];
                    [array1 removeObjectAtIndex:pathNumber];
                    d=[array1 count];
                    [tableView2 endUpdates];
                }
                else
                {
                    [tableView1 beginUpdates];
                    [tableView1 insertRowsAtIndexPaths:arrayOfPaths1 withRowAnimation:UITableViewRowAnimationTop];
                    for(int j=0;j<[arrayOfPaths1 count];j++)
                    {
                        NSIndexPath * tempIndexPath = (NSIndexPath *)([arrayOfPaths1 objectAtIndex:j]);
                        [array insertObject:[selectedCells1 objectAtIndex:j] atIndex:tempIndexPath.row];
                    }
                    c=[array count];
                    NSLog(@"%d", c);
                    [tableView1 endUpdates];

                    [tableView2 beginUpdates];

                    [tableView2 deleteRowsAtIndexPaths:arrayOfPaths1 withRowAnimation:UITableViewRowAnimationTop];
                    for(int j = 0;j < [arrayOfPaths1 count]; j++)
                    {
                        NSIndexPath * temp = (NSIndexPath *)[arrayOfPaths1 objectAtIndex:j];
                        [array1 removeObjectAtIndex:temp.row];
                    }
                    d=[array1 count];
                    [tableView2 endUpdates];

                }
                [selectedCells1 removeAllObjects];
                [arrayOfPaths1 removeAllObjects];

            }
            else
            {
                NSLog(@"else1");
            }
        }
    }

}

You can get the cell that you are touching. When u have that cell, you can store their values on a temp cell that you have to declare on your ".h", and remove from first table´s data source.

When you detect that touch has ended, if that touch ended on one of the tables, add the temporary cell to its dataSource, and make a reloadData. Else, if the touch didn´t end on one of the tables bounds, add temp cell to the original table.

For improve visual functionality, you could show the UITableViewCell on touch coordinates.

So, step by step:

  • In your ViewController declare: UITableviewCell * tempCell

  • Init that "tempCell" somewhere in your code with tempCell = [[UITableViewCell alloc]init]

  • With that method: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //Here you have selected row number; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //Here you have selected row number; } you can get selected row, so you can recover cell values from your data source. Store that values on "tempCell" and remove them from table´s datasource.

  • You can add to ViewController.view the UITableViewCell, if you want to show the cell while touching.

  • With - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; you get touch coordinates. With those coordinates, u can check if they are on one of your tables. If the coordinates belongs to one of your tables, add to their dataSource, clean "tempCell", (and remove the cellView if you were showing on the ViewController´s view) and finally do [tableView reloadData]; . Else, if coordinates doesn´t belongs to your tables, add the cell to the original datasource and clean "tempCell".

Sorry For my bad English :(

You can make a snapshot to the cell, and fill in a imageview. then remove the cell from the tableview. add the imageview to the superview , override touch events or add a pan-gesture when ready to drop the snapshot imageview , insert the cell to the new tableview and fullfill the data

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM