2014-04-03 14 views
10

Chcę zezwolić na domyślny ruch rzędu w trybie UITableView bez konieczności jego edycji i bez uszczerbku dla domyślnego zachowania UITableView.iOS - Zezwalaj na domyślny ruch wierszy w `UITableView` bez trybu edycji

movable cell

Powyższy wyświetla obraz komórka w trybie edycji z ruchem włączona.

Próbowałem po prostu działa for (UIView *subview in cell.subviews) (podczas gdy mój UITableView był w trybie edycji), ale przycisk nie odwróciła się:

<UITableViewCellScrollView: 0x8cabd80; frame = (0 0; 320 44); autoresize = W+H; gestureRecognizers = <NSArray: 0x8c9ba20>; layer = <CALayer: 0x8ca14b0>; contentOffset: {0, 0}> 

Jak można pozwolić/dodać przycisk „” ruchu bez włączania trybu edycji w mój UITableView?

Tworzenie i dodawanie UIButton z domyślnym function dla ruchu jest również opcją.

+1

Może spróbować metody w tym ostatnim artykule: http: //www.raywenderlich.com/63089/cookbook-moving-table-view-cells-with-a-long-press-gesture – Jack

+0

To może pracować i wiem, że ta metoda jest możliwa. Ale moje pytanie brzmi: jak to zrobić, używając domyślnego kodu ruchu komórki. –

+0

@AleksanderAzizi Czy mogę zapytać, dlaczego boisz się trybu edycji? –

Odpowiedz

20

Rzeczywiście robię coś podobnego w przypadku jednej z moich aplikacji. Wykorzystuje metody delegatów do edycji tabeli i trochę "podstępu" użytkownika. Wbudowana w 100% funkcjonalność Apple.

1 - Ustaw tabelę do edycji (robię to w viewWillAppear)

-(void)viewWillAppear:(BOOL)animated{ 
    [super viewWillAppear:animated]; 
    [self.tableView setEditing:YES]; 
} 

2 - ukryć ikonę domyślną akcesorium:

-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView 
     editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ 
     //remove any editing accessories (AKA) delete button 
     return UITableViewCellAccessoryNone; 
     } 

3 - Zachowaj edycji tryb przeniesienia wszystkiego w prawo (w komórce)

-(BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{ 
return NO; 
} 

4 - W tym momencie powinieneś być w stanie przeciągnąć komórki wokół siebie, nie wyglądając, jakby były w trybie edycji. Tutaj oszukujemy użytkownika. Stwórz własną ikonę "przenieś" (trzy linie w domyślnym przypadku, dowolna ikona w twoim przypadku) i dodaj obrazek w prawo tam, gdzie normalnie trafi na komórkę.

5 - Wreszcie, zaimplementuj metodę delegatów, aby zmienić rzeczywiste źródło danych.

-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ 

    //Get original id 
    NSMutableArray *originalArray = [self.model.items objectAtIndex:sourceIndexPath.section]; 
    Item * original = [originalArray objectAtIndex:sourceIndexPath.row]; 

    //Get destination id 
    NSMutableArray *destinationArray = [self.model.items objectAtIndex:destinationIndexPath.section]; 
    Item * destination = [destinationArray objectAtIndex:destinationIndexPath.row]; 

    CGPoint temp = CGPointMake([original.section intValue], [original.row intValue]); 

    original.row = destination.row; 
    original.section = destination.section; 

    destination.section = @(temp.x); 
    destination.row = @(temp.y); 

    //Put destination value in original array 
    [originalArray replaceObjectAtIndex:sourceIndexPath.row withObject:destination]; 

    //put original value in destination array 
    [destinationArray replaceObjectAtIndex:destinationIndexPath.row withObject:original]; 

    //reload tableview smoothly to reflect changes 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [UIView transitionWithView:tableView duration:duration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ 
      [tableView reloadData]; 
     } completion:NULL]; 
    }); 
} 
+0

Pomyślałem, że to może również działać, mam dokładnie ten sam kod, ale domyślne przesunięcie (po lewej) do usunięcia jest wyłączone, gdy 'UITableView' jest w trybie edycji. Ergo moje pytanie, w jaki sposób włączyć ruch wiersza bez użycia trybu edycji. –

+0

Jeśli potrzebujesz przesunąć w lewo, włącz go przy użyciu innej implementacji. Spójrz na moją aplikację, która używa tego, pod listą zakupów. To brzmi jak dokładnie to, czego szukasz. http://appstore.com/mealidea –

+0

Moja implementacja przeciągania jest tutaj podstawowa, ale jeśli umieścisz w komórce widok przewijania, możesz uzyskać ten sam efekt, który ma jabłko –

0

Jeśli nie chcesz, aby ustawić UITableView w trybie edycji, a następnie trzeba będzie na nowo zdolność do przeciągania wokół komórek.

Przedstawiam dość kompletne rozwiązanie, które umożliwia użytkownikowi przenoszenie rzędów w widocznym obszarze UITableView. Działa to, czy UITableView jest w trybie edycji, czy nie. Musisz go rozszerzyć, jeśli chcesz przewinąć tabelę, gdy wiersz jest przeciągany w pobliżu górnej lub dolnej części widocznego obszaru. Najprawdopodobniej będziesz musiał zgłosić przypadki niepowodzenia i skrajności.

@implementation TSTableViewController 
{ 
    NSMutableArray* _dataSource; 
} 

- (void) viewDidLoad 
{ 
    [super viewDidLoad]; 

    _dataSource = [NSMutableArray new]; 
    for (int i = 0 ; i < 10 ; i++) 
    { 
     [_dataSource addObject: [NSString stringWithFormat: @"cell %d", i]]; 
    } 
} 

- (void) longPress: (UILongPressGestureRecognizer*) lpgr 
{ 
    static NSString* dragCellData = nil; 
    static UIView* dragCellView = nil; 
    static NSInteger dragCellOffset = 0; 

    // determine the cell we're hovering over, etc: 
    CGPoint pt = [lpgr locationInView: self.tableView]; 
    NSIndexPath* ip = [self.tableView indexPathForRowAtPoint: pt]; 
    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath: ip]; 
    CGPoint ptInCell = [lpgr locationInView: cell]; 

    // where the current placeholder cell is, if any: 
    NSInteger placeholderIndex = [_dataSource indexOfObject: @"placeholder"]; 

    switch (lpgr.state) 
    { 
     case UIGestureRecognizerStateBegan: 
     { 
      // get a snapshot-view of the cell we're going to drag: 
      cell.selected = cell.highlighted = NO; 
      dragCellView = [cell snapshotViewAfterScreenUpdates: YES]; 
      dragCellView.clipsToBounds  = NO; 
      dragCellView.layer.shadowRadius = 10; 
      dragCellView.layer.shadowColor = [UIColor blackColor].CGColor; 
      dragCellView.layer.masksToBounds = NO; 
      dragCellView.frame = [cell convertRect: cell.bounds 
             toView: self.tableView.window]; 

      // used to position the dragCellView nicely: 
      dragCellOffset = ptInCell.y; 

      // the cell will be removed from the view hierarchy by the tableview, so transfer the gesture recognizer to our drag view, and add it into the view hierarchy: 
      [dragCellView addGestureRecognizer: lpgr]; 
      [self.tableView.window addSubview: dragCellView]; 


      // swap out the cell for a placeholder: 
      dragCellData = _dataSource[ip.row]; 
      _dataSource[ip.row] = @"placeholder"; 

      [self.tableView reloadRowsAtIndexPaths: @[ip] 
            withRowAnimation: UITableViewRowAnimationNone]; 

      break; 
     } 

     case UIGestureRecognizerStateChanged: 
     { 
      // where should we move the placeholder to? 
      NSInteger insertIndex = ptInCell.y < cell.bounds.size.height/2.0 ? ip.row : ip.row + 1; 
      if (insertIndex != placeholderIndex) 
      { 
       // remove from the datasource and the tableview: 
       [_dataSource removeObjectAtIndex: placeholderIndex]; 
       [self.tableView deleteRowsAtIndexPaths: @[ [NSIndexPath indexPathForRow: placeholderIndex inSection: 0] ] 
             withRowAnimation: UITableViewRowAnimationFade]; 
       // adjust: 
       if (placeholderIndex < insertIndex) 
       { 
        insertIndex--; 
       } 

       // insert to the datasource and tableview: 
       [_dataSource insertObject: @"placeholder" 
            atIndex: insertIndex]; 
       [self.tableView insertRowsAtIndexPaths: @[ [NSIndexPath indexPathForRow: insertIndex inSection: 0] ] 
             withRowAnimation: UITableViewRowAnimationFade]; 
      } 

      // move our dragCellView 
      CGRect f = dragCellView.frame; 
      f.origin.y = pt.y - dragCellOffset; 
      dragCellView.frame = f; 

      break; 
     } 

     case UIGestureRecognizerStateEnded: 
     { 
      // replace the placeholdercell with the cell we were dragging 
      [_dataSource replaceObjectAtIndex: placeholderIndex 
            withObject: dragCellData]; 
      [self.tableView reloadRowsAtIndexPaths: @[ [NSIndexPath indexPathForRow: placeholderIndex inSection: 0] ] 
            withRowAnimation: UITableViewRowAnimationFade]; 

      // reset state 
      [dragCellView removeFromSuperview]; 
      dragCellView = nil; 
      dragCellData = nil; 

      break; 
     } 

     default: 
     { 
      break; 
     } 
    } 
} 

#pragma mark - Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return _dataSource.count; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSString* cellData = _dataSource[indexPath.row]; 
    if ([cellData isEqualToString: @"placeholder" ]) 
    { 
     // an empty cell to denote where the "drop" would go 
     return [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault 
             reuseIdentifier: nil]; 
    } 

    // a cell... 
    UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault 
                reuseIdentifier: nil]; 

    // our "fake" move handle & gesture recognizer 

    UILongPressGestureRecognizer* lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget: self action: @selector(longPress:) ]; 
    lpgr.minimumPressDuration = 0.3; 

    UILabel* dragLabelView = [UILabel new]; 
    dragLabelView.text = @"☰"; 
    dragLabelView.userInteractionEnabled = YES; 
    [dragLabelView addGestureRecognizer: lpgr]; 
    [dragLabelView sizeToFit]; 

    cell.textLabel.text = cellData; 

    if (tableView.isEditing) 
    { 
     cell.editingAccessoryView = dragLabelView; 
    } 
    else 
    { 
     cell.accessoryView = dragLabelView; 
    } 

    return cell; 
} 

@end 
1

odpowiedź Williama Sokoła w Swift 3

1 - Ustawić stół do edycji (robię to w viewWillAppear)

override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated: animated) 
    tableView.setEditing(true, animated: false) 
} 

2 - Ukryj domyślną ikonę akcesoriów :

override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { 
    return .none 
} 
Tryb Przechowywać edycji przesuwaniu wszystko w prawo (w komórce)

override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool { 
    return false 
} 

4 - -

3 Nie wymagane w Swift 3

5 - Zmiana kolejności macierzy

Extra Uwaga:

Aby wybrać komórki tabeli, należy dodać następujący kod w pozycji viewWillAppear() Funkcja.

tableView.allowsSelectionDuringEditing = true