2011-06-28 52 views
15

我的問題是,這是否可行?如果是,您將如何處理此任務?ipad:從一個UITableViewController中拖出一個UITableViewCell並將其放入另一個

有誰知道已經在使用此功能的應用程序,或者在哪裏獲取一些示例代碼?

另外,如果我要在沒有太多的主題知識的情況下自行實現這個功能,那麼對於完成它需要多長時間,您會做出什麼估計?

另一件要提及的事情,因爲它可能使事情變得更加複雜:目標表在默認情況下處於editmode狀態,以便用戶可以重新排列單元格(使用附件視圖中的標準重新排序控件)掉在那裏。

編輯:

我只是試圖包括概念圖像的截圖在我的崗位。圖像左側顯示一張桌面,右側顯示灰色的下落區域。我的客戶說他也在其他應用程序上看到過,所以必須有某種我不知道的UI元素。

我還沒有在開發者資源庫中找到任何關於這種放置區域的內容,所以希望你們中的一位能夠給我指示或清理一下。

+0

檢查解決辦法了這一點:https://github.com/Ice3SteveFortune/i3-dragndrop – sf13579

回答

36

好吧,我自己實現了這一點,我對結果很滿意。您可以將單元格從左側(源表格)拖動到右側(目標表格),並拖動目標表格中的單元格進行重新編碼。如果您嘗試從右向左拖動一個單元格,它將被重新插入到開始拖動的位置(因此沒有任何反應)。目標表也支持刪除單元格,源表格則不支持。因此,這裏的完整代碼:

UIDropTableViewController.h

#import <UIKit/UIKit.h> 

@interface UIDropTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate> 
{ 
    UINavigationItem* srcTableNavItem; 
    UINavigationItem* dstTableNavItem; 

    UITableView*  srcTableView; 
    UITableView*  dstTableView; 
    UITableViewCell* draggedCell; 
    UIView*    dropArea; 

    NSMutableArray*  srcData; 
    NSMutableArray*  dstData; 
    id     draggedData; 

    BOOL   dragFromSource;  // used for reodering 
    NSIndexPath* pathFromDstTable; // used to reinsert data when reodering fails 
} 

@property (nonatomic, readonly) NSArray* srcData; 
@property (nonatomic, readonly) NSArray* dstData; 

- (id)initWithFrame:(CGRect)frame SourceData:(NSArray*)sourceData DestinationData:(NSArray*)destinationData; 

- (void)setSrcTableTitle:(NSString*)title; 
- (void)setDstTableTitle:(NSString*)title; 

@end 

UIDropTableViewController.m

#import "UIDropTableViewController.h" 

#define kCellIdentifier @"DropTableCell" 
#define kCellHeight 44 
#define kNavBarHeight 30 


// forward declaration of private helper methods 
@interface UIDropTableViewController() 

- (void)setupSourceTableWithFrame:(CGRect)frame; 
- (void)setupDestinationTableWithFrame:(CGRect)frame; 
- (void)initDraggedCellWithCell:(UITableViewCell*)cell AtPoint:(CGPoint)point; 

- (void)startDragging:(UIPanGestureRecognizer *)gestureRecognizer; 
- (void)startDraggingFromSrcAtPoint:(CGPoint)point; 
- (void)startDraggingFromDstAtPoint:(CGPoint)point; 

- (void)doDrag:(UIPanGestureRecognizer *)gestureRecognizer; 
- (void)stopDragging:(UIPanGestureRecognizer *)gestureRecognizer; 

- (UITableViewCell*)srcTableCellForRowAtIndexPath:(NSIndexPath*)indexPath; 
- (UITableViewCell*)dstTableCellForRowAtIndexPath:(NSIndexPath*)indexPath; 

@end 


@implementation UIDropTableViewController 

@synthesize srcData, dstData; 

#pragma mark - 
#pragma mark Public Methods 

- (void)setSrcTableTitle:(NSString*)title 
{ 
    srcTableNavItem.title = title; 
} 

- (void)setDstTableTitle:(NSString*)title 
{ 
    dstTableNavItem.title = title; 
} 

#pragma mark - 
#pragma mark UIViewController 

- (id)initWithFrame:(CGRect)frame SourceData:(NSArray*)sourceData DestinationData:(NSArray*)destinationData 
{ 
    self = [super init]; 
    if (self) 
    { 
     self.view.clipsToBounds = YES; 
     self.view.frame = frame; 
     int width = frame.size.width; 
     int height = frame.size.height; 

     // set up data 
     srcData = [[NSMutableArray alloc] initWithArray:sourceData]; 
     dstData = [[NSMutableArray alloc] initWithArray:destinationData]; 

     draggedCell = nil; 
     draggedData = nil; 
     pathFromDstTable = nil; 

     // set up views 
     [self setupSourceTableWithFrame:CGRectMake(0, 0, width/2, height)]; 
     [self setupDestinationTableWithFrame:CGRectMake(width/2, 0, width/2, height)]; 

     UIView* separator = [[UIView alloc] initWithFrame:CGRectMake(width/2, 0, 1, height)]; 
     separator.backgroundColor = [UIColor blackColor]; 
     [self.view addSubview:separator]; 
     [separator release]; 

     // set up gestures 
     UIPanGestureRecognizer* panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanning:)]; 
     [self.view addGestureRecognizer:panGesture]; 
     [panGesture release]; 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    [srcTableNavItem release]; 
    [dstTableNavItem release]; 

    [srcTableView release]; 
    [dstTableView release]; 
    [dropArea release]; 

    [srcData release]; 
    [dstData release]; 

    if(draggedCell != nil) 
     [draggedCell release]; 
    if(draggedData != nil) 
     [draggedData release]; 
    if(pathFromDstTable != nil) 
     [pathFromDstTable release]; 

    [super dealloc]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [srcTableView reloadData]; 
    [dstTableView reloadData]; 

    [UIView animateWithDuration:0.2 animations:^ 
    { 
     CGRect frame = dstTableView.frame; 
     frame.size.height = kCellHeight * [dstData count]; 
     dstTableView.frame = frame; 
    }]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    return UIInterfaceOrientationIsLandscape(interfaceOrientation); 
} 

#pragma mark - 
#pragma mark Helper methods for initialization 

- (void)setupSourceTableWithFrame:(CGRect)frame 
{ 
    srcTableNavItem = [[UINavigationItem alloc] init]; 
    srcTableNavItem.title = @"Source Table"; 

    CGRect navBarFrame = frame; 
    navBarFrame.size.height = kNavBarHeight; 

    UINavigationBar* navigationBar = [[UINavigationBar alloc] initWithFrame:navBarFrame]; 
    [navigationBar pushNavigationItem:srcTableNavItem animated:false]; 
    [navigationBar setTintColor:[UIColor lightGrayColor]]; 
    [self.view addSubview:navigationBar]; 
    [navigationBar release]; 

    CGRect tableFrame = frame; 
    tableFrame.origin.y = kNavBarHeight; 
    tableFrame.size.height -= kNavBarHeight; 

    srcTableView = [[UITableView alloc] initWithFrame:tableFrame]; 
    [srcTableView setDelegate:self]; 
    [srcTableView setDataSource:self]; 
    [self.view addSubview:srcTableView]; 
} 

- (void)setupDestinationTableWithFrame:(CGRect)frame 
{ 
    dstTableNavItem = [[UINavigationItem alloc] init]; 
    dstTableNavItem.title = @"Destination Table"; 

    CGRect navBarFrame = frame; 
    navBarFrame.size.height = kNavBarHeight; 

    UINavigationBar* navigationBar = [[UINavigationBar alloc] initWithFrame:navBarFrame]; 
    [navigationBar pushNavigationItem:dstTableNavItem animated:false]; 
    [navigationBar setTintColor:[UIColor lightGrayColor]]; 
    [self.view addSubview:navigationBar]; 
    [navigationBar release]; 

    CGRect dropAreaFrame = frame; 
    dropAreaFrame.origin.y = kNavBarHeight; 
    dropAreaFrame.size.height -= kNavBarHeight; 

    dropArea = [[UIView alloc] initWithFrame:dropAreaFrame]; 
    [dropArea setBackgroundColor:[UIColor grayColor]]; 
    [self.view addSubview:dropArea]; 

    CGRect contentFrame = dropAreaFrame; 
    contentFrame.origin = CGPointMake(0, 0); 

    UILabel* dropAreaLabel = [[UILabel alloc] initWithFrame:contentFrame]; 
    dropAreaLabel.backgroundColor = [UIColor clearColor]; 
    dropAreaLabel.font = [UIFont boldSystemFontOfSize:12]; 
    dropAreaLabel.textAlignment = UITextAlignmentCenter; 
    dropAreaLabel.textColor = [UIColor whiteColor]; 
    dropAreaLabel.text = @"Drop items here..."; 
    [dropArea addSubview:dropAreaLabel]; 
    [dropAreaLabel release]; 

    CGRect tableFrame = contentFrame; 
    tableFrame.size.height = kCellHeight * [dstData count]; 

    dstTableView = [[UITableView alloc] initWithFrame:tableFrame]; 
    [dstTableView setEditing:YES]; 
    [dstTableView setDelegate:self]; 
    [dstTableView setDataSource:self]; 
    [dropArea addSubview:dstTableView]; 
} 

- (void)initDraggedCellWithCell:(UITableViewCell*)cell AtPoint:(CGPoint)point 
{ 
    // get rid of old cell, if it wasn't disposed already 
    if(draggedCell != nil) 
    { 
     [draggedCell removeFromSuperview]; 
     [draggedCell release]; 
     draggedCell = nil; 
    } 

    CGRect frame = CGRectMake(point.x, point.y, cell.frame.size.width, cell.frame.size.height); 

    draggedCell = [[UITableViewCell alloc] init]; 
    draggedCell.selectionStyle = UITableViewCellSelectionStyleGray; 
    draggedCell.textLabel.text = cell.textLabel.text; 
    draggedCell.textLabel.textColor = cell.textLabel.textColor; 
    draggedCell.highlighted = YES; 
    draggedCell.frame = frame; 
    draggedCell.alpha = 0.8; 

    [self.view addSubview:draggedCell]; 
} 

#pragma mark - 
#pragma mark UIGestureRecognizer 

- (void)handlePanning:(UIPanGestureRecognizer *)gestureRecognizer 
{ 
    switch ([gestureRecognizer state]) { 
     case UIGestureRecognizerStateBegan: 
      [self startDragging:gestureRecognizer]; 
      break; 
     case UIGestureRecognizerStateChanged: 
      [self doDrag:gestureRecognizer]; 
      break; 
     case UIGestureRecognizerStateEnded: 
     case UIGestureRecognizerStateCancelled: 
     case UIGestureRecognizerStateFailed: 
      [self stopDragging:gestureRecognizer]; 
      break; 
     default: 
      break; 
    } 
} 

#pragma mark - 
#pragma mark Helper methods for dragging 

- (void)startDragging:(UIPanGestureRecognizer *)gestureRecognizer 
{ 
    CGPoint pointInSrc = [gestureRecognizer locationInView:srcTableView]; 
    CGPoint pointInDst = [gestureRecognizer locationInView:dstTableView]; 

    if([srcTableView pointInside:pointInSrc withEvent:nil]) 
    { 
     [self startDraggingFromSrcAtPoint:pointInSrc]; 
     dragFromSource = YES; 
    } 
    else if([dstTableView pointInside:pointInDst withEvent:nil]) 
    { 
     [self startDraggingFromDstAtPoint:pointInDst]; 
     dragFromSource = NO; 
    } 
} 

- (void)startDraggingFromSrcAtPoint:(CGPoint)point 
{ 
    NSIndexPath* indexPath = [srcTableView indexPathForRowAtPoint:point]; 
    UITableViewCell* cell = [srcTableView cellForRowAtIndexPath:indexPath]; 
    if(cell != nil) 
    { 
     CGPoint origin = cell.frame.origin; 
     origin.x += srcTableView.frame.origin.x; 
     origin.y += srcTableView.frame.origin.y; 

     [self initDraggedCellWithCell:cell AtPoint:origin]; 
     cell.highlighted = NO; 

     if(draggedData != nil) 
     { 
      [draggedData release]; 
      draggedData = nil; 
     } 
     draggedData = [[srcData objectAtIndex:indexPath.row] retain]; 
    } 
} 

- (void)startDraggingFromDstAtPoint:(CGPoint)point 
{ 
    NSIndexPath* indexPath = [dstTableView indexPathForRowAtPoint:point]; 
    UITableViewCell* cell = [dstTableView cellForRowAtIndexPath:indexPath]; 
    if(cell != nil) 
    { 
     CGPoint origin = cell.frame.origin; 
     origin.x += dropArea.frame.origin.x; 
     origin.y += dropArea.frame.origin.y; 

     [self initDraggedCellWithCell:cell AtPoint:origin]; 
     cell.highlighted = NO; 

     if(draggedData != nil) 
     { 
      [draggedData release]; 
      draggedData = nil; 
     } 
     draggedData = [[dstData objectAtIndex:indexPath.row] retain]; 

     // remove old cell 
     [dstData removeObjectAtIndex:indexPath.row]; 
     [dstTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationMiddle]; 
     pathFromDstTable = [indexPath retain]; 

     [UIView animateWithDuration:0.2 animations:^ 
     { 
      CGRect frame = dstTableView.frame; 
      frame.size.height = kCellHeight * [dstData count]; 
      dstTableView.frame = frame; 
     }]; 

    } 
} 

- (void)doDrag:(UIPanGestureRecognizer *)gestureRecognizer 
{ 
    if(draggedCell != nil && draggedData != nil) 
    { 
     CGPoint translation = [gestureRecognizer translationInView:[draggedCell superview]]; 
      [draggedCell setCenter:CGPointMake([draggedCell center].x + translation.x, 
               [draggedCell center].y + translation.y)]; 
     [gestureRecognizer setTranslation:CGPointZero inView:[draggedCell superview]]; 
    } 
} 

- (void)stopDragging:(UIPanGestureRecognizer *)gestureRecognizer 
{ 
    if(draggedCell != nil && draggedData != nil) 
    { 
     if([gestureRecognizer state] == UIGestureRecognizerStateEnded 
      && [dropArea pointInside:[gestureRecognizer locationInView:dropArea] withEvent:nil]) 
     {    
      NSIndexPath* indexPath = [dstTableView indexPathForRowAtPoint:[gestureRecognizer locationInView:dstTableView]]; 
      if(indexPath != nil) 
      { 
       [dstData insertObject:draggedData atIndex:indexPath.row]; 
       [dstTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationMiddle]; 
      } 
      else 
      { 
       [dstData addObject:draggedData]; 
       [dstTableView reloadData]; 
      } 
     } 
     else if(!dragFromSource && pathFromDstTable != nil) 
     { 
      // insert cell back where it came from 
      [dstData insertObject:draggedData atIndex:pathFromDstTable.row]; 
      [dstTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:pathFromDstTable] withRowAnimation:UITableViewRowAnimationMiddle]; 

      [pathFromDstTable release]; 
      pathFromDstTable = nil; 
     } 

     [UIView animateWithDuration:0.3 animations:^ 
     { 
      CGRect frame = dstTableView.frame; 
      frame.size.height = kCellHeight * [dstData count]; 
      dstTableView.frame = frame; 
     }]; 

     [draggedCell removeFromSuperview]; 
     [draggedCell release]; 
     draggedCell = nil; 

     [draggedData release]; 
     draggedData = nil; 
    } 
} 

#pragma mark - 
#pragma mark UITableViewDataSource 

- (BOOL)tableView:(UITableView*)tableView canMoveRowAtIndexPath:(NSIndexPath*)indexPath 
{ 
    // disable build in reodering functionality 
    return NO; 
} 

- (void)tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // enable cell deletion for destination table 
    if([tableView isEqual:dstTableView] && editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     [dstData removeObjectAtIndex:indexPath.row]; 
     [dstTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 

     [UIView animateWithDuration:0.2 animations:^ 
     { 
      CGRect frame = dstTableView.frame; 
      frame.size.height = kCellHeight * [dstData count]; 
      dstTableView.frame = frame; 
     }]; 
    } 
} 

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    // tell our tables how many rows they will have 
    int count = 0; 
    if([tableView isEqual:srcTableView]) 
    { 
     count = [srcData count]; 
    } 
    else if([tableView isEqual:dstTableView]) 
    { 
     count = [dstData count]; 
    } 
    return count; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return kCellHeight; 
} 

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath 
{ 
    UITableViewCell* result = nil; 
    if([tableView isEqual:srcTableView]) 
    { 
     result = [self srcTableCellForRowAtIndexPath:indexPath]; 
    } 
    else if([tableView isEqual:dstTableView]) 
    { 
     result = [self dstTableCellForRowAtIndexPath:indexPath]; 
    } 

    return result; 
} 

#pragma mark - 
#pragma mark Helper methods for table stuff 

- (UITableViewCell*)srcTableCellForRowAtIndexPath:(NSIndexPath*)indexPath 
{ 
    // tell our source table what kind of cell to use and its title for the given row 
    UITableViewCell *cell = [srcTableView dequeueReusableCellWithIdentifier:kCellIdentifier]; 
    if (cell == nil) 
    { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
             reuseIdentifier:kCellIdentifier] autorelease]; 

     cell.selectionStyle = UITableViewCellSelectionStyleNone; 
     cell.textLabel.textColor = [UIColor darkGrayColor]; 
    } 
    cell.textLabel.text = [[srcData objectAtIndex:indexPath.row] description]; 

    return cell; 
} 

- (UITableViewCell*)dstTableCellForRowAtIndexPath:(NSIndexPath*)indexPath 
{ 
    // tell our destination table what kind of cell to use and its title for the given row 
    UITableViewCell *cell = [dstTableView dequeueReusableCellWithIdentifier:kCellIdentifier]; 
    if (cell == nil) 
    { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
             reuseIdentifier:kCellIdentifier] autorelease]; 

     cell.selectionStyle = UITableViewCellSelectionStyleNone; 
     cell.textLabel.textColor = [UIColor darkGrayColor]; 
    } 
    cell.textLabel.text = [[dstData objectAtIndex:indexPath.row] description]; 

    return cell; 
} 

@end 

下面是如何使用它的一個例子:

NSArray* srcData = [NSArray arrayWithObjects:@"item0", @"item1", @"item2", @"item3", @"item4", nil]; 
NSArray* dstData = [NSArray arrayWithObjects:@"item5", @"item6", nil]; 

dropTable = [[UIDropTableViewController alloc] initWithFrame:CGRectMake(100, 100, 600, 500) SourceData:srcData DestinationData:dstData]; 
[dropTable setSrcTableTitle:@"Bla"]; 
[dropTable setDstTableTitle:@"Blub"]; 
[[dropTable.view layer] setBorderColor:[[UIColor darkGrayColor] CGColor]]; 
[[dropTable.view layer] setBorderWidth:1]; 
[[dropTable.view layer] setCornerRadius:2]; 
[self.view addSubview:dropTable.view]; 

接着,在你完成編輯你剛剛閱讀dropTable.dstData並繼續使用它的前夕你想做什麼。

UIDropTableViewController.m你可能想調整initDraggedCellWithCell,srcTableCellForRowAtIndexPathdstTableCellForRowAtIndexPath爲你自​​己的需要,只要細胞表示去。

+1

嘿感謝了很多它的作品精湛的代碼。 – Dhara

+0

我用上面的代碼作爲我需要的基礎。非常有效地寫。謝謝 – Jatin

+0

上面的代碼工作很好 – Jingwei

4

我只需要解決類似的問題。這是一個鏈接到github上編譯和運行的例子。

https://github.com/luminixinc/UITableViewDragAndDropExample.git 

享受。

1

我知道這是一個非常古老的問題,但我最近實施的代碼christoph gave in his answer在一個簡單的觀點輔助類 - 想這可能是有用的:

i3-dragndrop

它同時支持UITableViewsUICollectionViews作爲來源和目的地。

UPDATE

我剛剛意識到上述庫的版本2:BetweenKit。它建立在原始概念的基礎上,但支持多種新功能,如多個目標集合,自定義渲染等等。希望能幫助到你 !

相關問題