2012-11-07 9 views
16

Ich habe Probleme mit Tabellenansicht Zellen behalten ihren "ausgewählten" Zustand beim Scrollen der Tabelle. Hier ist der relevante Code:UITableView ausgewählte Zelle bleibt beim Scrollen nicht ausgewählt

@property (nonatomic, strong) NSIndexPath *selectedIndexPath; 

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    self.selectedIndexPath = indexPath; 
    //do other stuff 
} 

-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    MyCustomCell_iPhone* cell = [tableView dequeueReusableCellWithIdentifier:@"MyCustomCell_iPhone"]; 

    if (cell == nil) 
     cell = [[[NSBundle mainBundle] loadNibNamed:@"MyCustomCell_iPhone" owner:self options:nil] objectAtIndex:0]; 

    if ([indexPath compare: self.selectedIndexPath] == NSOrderedSame) { 
     [cell setSelected:YES animated:NO]; 
    } 

    return cell; 
} 

Und für die Zelle:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated 
{ 
    [super setSelected:selected animated:animated]; 

    if (selected) { 
     self.selectedBg.hidden = NO; 
    }else{ 
     self.selectedBg.hidden = YES; 
    } 
} 

- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated 
{ 
    [super setHighlighted:highlighted animated:animated]; 

    if (highlighted) { 
     self.selectedBg.hidden = NO; 
    }else{ 
     self.selectedBg.hidden = YES; 
    } 
} 

Wie kann ich die ausgewählte Zelle markiert bleiben erhalten? Wenn ich es vom Bildschirm scrollt, wenn es auf dem Bildschirm zurück scrollt, erscheint es in seinem nicht ausgewählten Zustand (mit seinem ausgewählten Bg ausgeblendet).

EDIT: Entfernen Sie die SetHighlighted-Methode aus der Zelle behebt das Problem. Das bedeutet jedoch, dass ich beim Drücken der Tabellenzelle keinen markierten Zustand erhalte. Ich würde gerne die Lösung dafür wissen.

Antwort

13

Hatte das gleiche Problem, die AccessoryView der ausgewählten Zelle verschwand auf Scroll. Mein Kollege hat für dieses Problem einen hübschen Hack gefunden. Der Grund dafür ist, dass in iOS 7 unter touchesBegan das Ereignis UITableView die ausgewählte Zelle abwählt und die angetastete Zelle auswählt. In iOS 6 passiert es nicht und beim Scrollen bleibt die ausgewählte Zelle ausgewählt. Um dasselbe Verhalten in iOS 7 zu erhalten, versuchen Sie Folgendes:

1) Aktivieren Sie die Mehrfachauswahl in Ihrem TableView. Zum

2) zu Tableview Delegatmethode DidSelectRowAtIndexPath und deaktivieren Zelle mit dem Code aufsetzten:

NSArray *selectedRows = [tableView indexPathsForSelectedRows]; 
for(NSIndexPath *i in selectedRows) 
{ 
    if(![i isEqual:indexPath]) 
    { 
     [tableView deselectRowAtIndexPath:i animated:NO]; 
    } 
} 

behoben mein Problem! Ich hoffe es wäre hilfreich, tut mir leid für mein schlechtes Englisch.

+1

Großartig! Diese Lösung hat für mich gut funktioniert. Aber ich habe ein Problem gefunden, wenn die ausgewählte Zeile erneut ausgewählt wird. Dann wird es abgewählt. Ich habe dieses UITableView Delegatmethode hinzugefügt, um das Problem zu lösen: - (NSIndexPath *) tableview: (UITableView *) tableview willDeselectRowAtIndexPath: (NSIndexPath *) indexPath { UITableViewCell * cell = [Tableview cellForRowAtIndexPath: indexPath]; if ([cell isSelected]) { Rückgabe nil; } Rückgabe IndexPfad; } – mlabraca

0

Haben Sie versucht, die Zeilen der Indexpfade anstelle des gesamten Indexpfadobjekts zu vergleichen?

if ((indexPath.row == self.selectedIndexPath.row) && (indexPath.section == self.selectedIndexPath.section)) { 
    [cell setSelected:YES animated:NO]; 
} 
+0

Dies würde nicht funktionieren, da es mehrere Abschnitte gibt. – soleil

+0

Ich aktualisierte den Code, um die Überprüfung für den Abschnitt sowie die Zeile einzuschließen. – danielM

0

Hier ist die Lösung, die ich gefunden habe - und es fühlt sich nicht einmal hacky.

1) Implementieren Sie -scrollViewWillBeginDragging: und -scrollViewWillEndDragging:withVelocity:targetContentOffset: und markieren Sie manuell die Zelle für die ausgewählte Zeile (falls vorhanden) während des Bildlaufs.

-Mine aussehen:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollview { 
    self.scrollViewIsDragging = YES; 

    if([self.tableView indexPathForSelectedRow]) { 
     [[self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]] setHighlighted:YES]; 
    } 
} 

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 
    self.scrollViewIsDragging = NO; 

    if([self.tableView indexPathForSelectedRow]) { 
     [[self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]] setHighlighted:NO]; 
    } 
} 

Die scrollViewIsDragging Eigenschaft es ist so, dass in -tableView:cellForRowAtIndexPath: können wir sicherstellen, alle neu ausgereiht Zellen die richtige Markierung haben (zB wenn die Zelle für die ausgewählte Zeile wird auf den Bildschirm gescrollt nachdem er nicht auf dem Bildschirm war). Der zugehörige Teil dieser Methode sieht wie folgt aus:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    // ... cell creation/configuration ... 

    if(self.scrollViewIsDragging && [[tableView indexPathForSelectedRow] isEqual:indexPath]) { 
     [cell setHighlighted:YES animated:NO]; 
    } 

}

... und dort haben Sie es. Die Zelle für die selectedRow bleibt beim Scrollen markiert.

+0

Der eine Vorbehalt, der meiner Meinung nach das richtige Verhalten ist (zumindest in meinem Fall), ist, dass eine zögerliche Berührung einer anderen Zelle diese Zelle kurzzeitig hervorheben kann, bevor der Benutzer mit dem Scrollen beginnt. Wenn jemand einen klugen Umgang damit hat, würde ich es gerne hören. –

6

Ich weiß meine Methode ist nicht sehr orthodox aber scheint zu funktionieren.Hier ist meine Lösung:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    if cell.selected { 
     cell.selected = true 
    } else { 
     cell.selected = false 
    } 
} 

Sie alle Methoden implementieren müssen Sie auf Ihrem Beitrag erwähnt und (@soleil)

+0

Dies ist eine sehr einfache Lösung und funktioniert für mich – Joqus

+0

das ist die einzige Lösung hier, die mir geholfen hat. Ich habe es in Obj-C innerhalb meiner 'UITableViewController' Unterklasse implementiert und es war nicht einmal notwendig,' selectedIndexPath' in einer Variablen als @soleil zu speichern, wenn Sie '[self setClearsSelectionOnViewWillAppear: NO] verwenden;' – skornos

+0

können Sie einfach tun ' cell.selected = cell.selected', obwohl es nicht so lesbar ist – sbru

2

iOS 8.7 sowohl deaktivieren Sie die Zelle beim Scrollen beginnt (als Alexander Larionov wies darauf hin,).

Eine einfachere Lösung für mich war dieses UIScrollViewDelegate Methode in meinem Viewcontroller zu implementieren:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 
    NSInteger theRow  = [self currentRowIndex]; // my own method 
    NSIndexPath *theIndexPath = [NSIndexPath indexPathForRow:theRow inSection:0]; 
    [self.myTableView selectRowAtIndexPath:theIndexPath 
            animated:NO 
          scrollPosition:UITableViewScrollPositionNone]; 
} 

Das funktioniert, weil meine Viewcontroller die Delegierten UITableView ist, und UITableView erbt von UIScrollView.

+1

Dies ist eine alternative Lösung zu Ihrer NSIndexPath * indexPath = [_tableView indexPathForSelectedRow]; [_tableView selectRowAtIndexPath: indexPfad animiert: NO scrollPosition: UITableViewScrollPositionNone]; – alexiscrack3

0

UITableViewCell hat eine BOOL-Eigenschaft "ausgewählt". Jedes Mal, wenn Sie die Zelle laden, überprüft den Zustand der ausgewählten und entsprechend Auswahl oder Abwahl machen wie in cellForRowAtIndexPath Definition folgt:

if (cell.selected) { 
    // Maintain selected state 
} 
else{ 
    // Maintain deselected state 
} 
1

Wenn Sie die gleiche Sache in Swift erreichen wollen hier dann der Code. Übrigens verwende ich Xcode 7.2 mit Swift 2.1.

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    if cell.selected == true{ 
     cell.selected = true 
     cell.backgroundColor = UIColor.blackColor() 
    }else{ 
     cell.backgroundColor = tableViewCellColor //Don't panic its my own custom color created for the table cells. 
     cell.selected = false 
    } 
} 

andere Anpassung Tun Sie, was immer Sie wollen ..

Dank ..

Hope this geholfen.

0

Swift 3 -Lösung, 2017.

I befestigt, das Problem mit dieser einfachen Codezeile:

cell.isSelected = tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false 

Innerhalb der tableview (tableview: cellForRowAt indexPath :) Methode:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    // Dequeue a reusable cell 
    if let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID") { 

     cell.isSelected = tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false 

     // Now you can safely use cell.isSelected to configure the cell 

     // ...your configurations here 

     return cell 
    } 

    return UITableViewCell() 
} 
1

Ich verwende Xcode 9.0.1 und Swift 4.0. Ich habe festgestellt, dass die folgenden Codes meine Auswahlmarkierung lösten, wenn Zellen auf dem Bildschirm und zurück verschoben wurden:

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { 
    if cell.isSelected { 
     cell.accessoryType = .checkmark 
    } else { 
     cell.accessoryType = .none 
    } 
} 
Verwandte Themen