2010-10-25 3 views
6

Zastanawiam się, czy ktoś ma link do dobrego samouczka lub może wskazać mi w dobrym kierunku, aby odtworzyć komórki "przeciągnij, aby zmienić kolejność" w UITableView takich jak Epic Win App. Podstawową ideą jest dotknięcie elementu listy i przytrzymanie go, a następnie przeciągnięcie do miejsca, w którym ma się znaleźć element. Każda pomoc będzie bardzo ceniona.Niestandardowe UITableView reorder

+0

jak to osiągnąć, jeśli mamy wiele sekcji z jednym wierszem dla każdej sekcji ???? Proszę, pomóż mi! – ravoorinandan

Odpowiedz

7

Jest to dość proste - prawdopodobnie dlatego nie ma wyraźnego samouczka w tej sprawie.

Po prostu utwórz normalnie UITableView, ale ustaw showsReorderControl każdej komórki na PRAWDA. Po przejściu do trybu edycji (normalnie po naciśnięciu przycisku "edytuj" i ustawieniu wartości "Edycja" opcji UITableView na TRUE) w komórkach pojawią się paski zmiany kolejności.

Uwaga:

Jeśli źródło danych implementuje tableView:canMoveRowAtIndexPath: - i to zwraca „NIE” - bary Zmiana kolejności nie pojawi.

Musisz również wykonać –tableView:moveRowAtIndexPath:toIndexPath: w delegacie źródła danych.

+5

Jedną rzeczą, którą chciałbym móc zrobić, jest zastąpienie przycisku i uczynienie z całej komórki przycisku. Więc możesz po prostu przeciągnąć komórkę. Czy znasz jakiś sposób, aby to zrobić? Lub krok do przodu, jak to zrobić? – Pudgeball

+0

Bardzo łatwo jest podklasować UITableCellView na wszystko, czego potrzebujesz - więc byłoby po prostu kwestią zrobienia twojego z własnym przyciskiem/obszarem w pasku reorganizacji. – Brad

+0

OK, dziękuję za pomoc :) – Pudgeball

13

Najprostszym sposobem, za pomocą wbudowanych metod jest następująca:

Najpierw ustawić komórkę tabeli, aby mieć kontrolę nad pokazuje kolejność. Najprostszy przykład (przy użyciu ARC):

to zakładając NSMutableArray *things został stworzony gdzieś indziej w tej klasie

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"do not leak me"]; 
    if (!cell) { 
     cell = [[UITableViewCell alloc] init]; 
     cell.showsReorderControl = YES; 
    } 
    cell.textLabel.text = [things objectAtIndex:indexPath.row]; 
    return cell; 
} 

zaimplementować dwa UITableViewDelegate metod, takich jak to:

Ten sposób opowiada tableView jest mogą zostać zreorganizowane

-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 
    return YES; 
} 

to jest, gdy zmiana kolejności tableView faktycznie dzieje

-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { 
    id thing = [things objectAtIndex:sourceIndexPath.row]; 
    [things removeObjectAtIndex:sourceIndexPath.row]; 
    [things insertObject:thing atIndex:destinationIndexPath.row]; 

} 

, a następnie jakoś, gdzieś, ustaw edycję na wartość true. To jest jeden z przykładów tego, jak możesz to zrobić. Aby mogła zostać zmieniona, tableView musi być w trybie edycji.

- (IBAction)doSomething:(id)sender { 
    self.table.editing = YES; 
} 

Nadzieja, która służy jako konkretny przykład.

+0

Pytanie wyraźnie zaznaczone, aby podać niestandardową opcję zmiany kolejności, a nie wartość domyślną. – Unome

+0

@Nie. Nie. OP wybrał opcję Zaakceptowana odpowiedź, która jest w zasadzie bardziej skróconą wersją mojej odpowiedzi. Dzięki. –

+0

Przyjęta odpowiedź, jak pan powiedział, jest rozwodnioną wersją tego, o co pytano. Wysłałem działającą podklasę UITableView. – Unome

3

To rozwiązanie będzie działać podobnie do aplikacji Przypomnienia na OSX, która pozwala na zmianę kolejności komórek poprzez ich ciągłe trzymanie i przeciąganie.

Stworzyłem podklasę UITableView, która pozwala przeciągać i zmieniać kolejność komórek bez konieczności posiadania editing lub używania standardowych uchwytów do zmiany kolejności.

Podstawowa zasada polega na tym, że używam dotknięć, które się zaczęły, i dotknięć zakończonych, aby uzyskać komórkę, która została dotknięta. Następnie utworzę fałszywy widok, który jest tak naprawdę tylko zrzutem ekranowym widoku, który stuknąłeś i przesuwał go tam iz powrotem, zamieniając komórki w tle. Kiedy użytkownik puści, a następnie odkryję oryginalny widok.

class ReorderTableView: UITableView { 

var customView:UIImageView? 
var oldIndexPath:NSIndexPath? 

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    guard let touch1 = touches.first else{ 
     return 
    } 

    oldIndexPath = self.indexPathForRowAtPoint(touch1.locationInView(self)) 
    guard (oldIndexPath != nil) else{ 
     return 
    } 
    let oldCell = self.cellForRowAtIndexPath(self.oldIndexPath!) 

    customView = UIImageView(frame: CGRectMake(0, touch1.locationInView(self).y - 20, self.frame.width, 40)) 
    customView?.image = screenShotView(oldCell!) 
    customView?.layer.shadowColor = UIColor.blackColor().CGColor 
    customView?.layer.shadowOpacity = 0.5 
    customView?.layer.shadowOffset = CGSizeMake(1, 1) 

    self.addSubview(customView!) 
    oldCell?.alpha = 0 
} 

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 

    guard let touch1 = touches.first else{ 
     return 
    } 
    let newIndexPath = self.indexPathForRowAtPoint(touch1.locationInView(self)) 
    guard newIndexPath != nil else{ 
     return 
    } 
    guard oldIndexPath != nil else{ 
     return 
    } 
    if newIndexPath != oldIndexPath{ 
     self.moveRowAtIndexPath(oldIndexPath!, toIndexPath: newIndexPath!) 
     oldIndexPath = newIndexPath 
     self.cellForRowAtIndexPath(self.oldIndexPath!)!.alpha = 0 
    } 
    self.customView!.frame.origin = CGPointMake(0, touch1.locationInView(self).y - 20) 
} 

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    self.customView?.removeFromSuperview() 
    self.customView = nil 
    guard (oldIndexPath != nil) else{ 
     return 
    } 
    self.cellForRowAtIndexPath(self.oldIndexPath!)!.alpha = 1 
} 

func screenShotView(view: UIView) -> UIImage? { 

    let rect = view.bounds 
    UIGraphicsBeginImageContextWithOptions(rect.size,true,0.0) 
    let context = UIGraphicsGetCurrentContext() 

    CGContextTranslateCTM(context, 0, -view.frame.origin.y); 
    self.layer.renderInContext(context!) 
    let capturedImage = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
    return capturedImage 
} 

} 

W końcu można zmienić kolejność komórek bez konieczności używania uchwytów. Można go rozszerzyć na różne gesty lub tryby w zależności od przypadku użycia, ale zostawiłem to jako wersję waniliową.Daj mi znać, jeśli masz jakieś pytania.

Aktualizacja:

Niektóre ostrzeżenia znalazłem. Bardzo ważne jest, aby dowiedzieć się, w jaki sposób korzystać z przewijania i odpowiednio je modyfikować. Na przykład, kiedy wyśmiałem go, ustawiłem scrollingEnabled = false. Na dłuższą metę chciałem przewijać, więc zmieniłem kod tak, aby uruchamiał tę funkcję tylko na dłużej niż 0.25 (użyłem do tego niektórych timerów). Następnie tymczasowo wyłączałem przewijanie w tym okresie i ponownie włączałem po zakończeniu.

+0

Co sprawia, że ​​myślisz, że PO chce tego? Przyjęta odpowiedź używa uchwytów. Dziękuję Ci. –

+1

jego pytanie: "Podstawowym pomysłem jest dotknięcie elementu listy i przeciągnięcie do miejsca, w którym ma się znaleźć element" nie określało, że chciał używać uchwytów, a tytuł "Zmiana kolejności niestandardowej" oznacza brak użycia domyślne metody. Miałem podobny problem i żadna odpowiedź tutaj nie pomogła mi. Próbowałem udzielić odpowiedzi, która pomogłaby tym, którzy mają podobne problemy. Przyjęta odpowiedź nie = właściwa odpowiedź. Dziękuję Ci. – Unome

+0

Wszystko dobrze. Jeśli chcesz dodać kolejną odpowiedź, która pokazuje inne podejście, które jest idealne. Nie ma potrzeby trzepania się innymi odpowiedziami, aby promować twoje +1 –