Jestem nowicjuszem w rozwoju iOS. Chcę dodać znacznik wyboru do mojego, UITableViewCell
gdy jest zaznaczony. Zaznaczenie powinno zostać usunięte po wybraniu innego wiersza. Jak bym to zrobił?
ios
uitableview
Suchi
źródło
źródło
W metodzie UITableViewDatasource:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if(cell == nil ) { cell =[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } if ([indexPath compare:self.lastIndexPath] == NSOrderedSame) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } return cell; } // UITableView Delegate Method -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { self.lastIndexPath = indexPath; [tableView reloadData]; }
LastIndexPath to plik
property(strong) NSIndexPath* lastIndexPath;
źródło
Zauważyłem, że ponowne załadowanie danych w brzydki sposób przerywa animację odznaczania.
Ta implementacja Swift czysto dodaje / usuwa znaczniki wyboru i usuwa zaznaczenie wiersza:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if self.lastSelection != nil { self.myTableView.cellForRowAtIndexPath(self.lastSelection)?.accessoryType = .None } self.myTableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark self.lastSelection = indexPath self.myTableView.deselectRowAtIndexPath(indexPath, animated: true) }
gdzie
lastSelection
jest zadeklarowany jakovar lastSelection: NSIndexPath!
Żadna dodatkowa aktywność nie jest
cellForRowAtIndexPath
potrzebna. Nie powinno być trudne do odtworzenia w Obj-C.źródło
Aby ustawić znacznik wyboru:
UITableViewCell *cell = ...; cell.accessoryType = UITableViewCellAccessoryCheckmark;
Aby zaznaczyć / odznaczyć komórkę:
[cell setSelected:TRUE animated:TRUE]; // select [cell setSelected:FALSE animated:TRUE]; // deselect
Aby odznaczyć poprzednią komórkę, użyj NSIndexPath * lastSelected ivar do śledzenia ostatnio wybranej komórki:
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { if (self.lastSelected==indexPath) return; // nothing to do // deselect old UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected]; old.accessoryType = UITableViewCellAccessoryNone; [old setSelected:FALSE animated:TRUE]; // select new UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryCheckmark; [cell setSelected:TRUE animated:TRUE]; // keep track of the last selected cell self.lastSelected = indexPath; }
źródło
Zaktualizuj Swift 4
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark } func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath)?.accessoryType = .none }
źródło
extension ViewController : UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.dataArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = dataArray[indexPath.row] if selectedData.contains(dataArray[indexPath.row]) { cell.accessoryType = .checkmark }else{ cell.accessoryType = .none } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if selectedData.contains(dataArray[indexPath.row]) { selectedData.removeLast() tableView.cellForRow(at: indexPath)?.accessoryType = .none }else { selectedData.removeAll() selectedData.append(dataArray[indexPath.row]) tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark } print(selectedData) } func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath)?.accessoryType = .none } }
na podstawie utworzonego widoku tabeli dataArray ... podobnie wziąłem pustą tablicę i za każdym razem, gdy użytkownik dotknie komórki, na podstawie indexValue z dataArray zapisałem ten obiekt w selectedDataArray
Jeśli chodzi o pytanie, to jest jak ... Pytanie ma wiele opcji (odpowiedzi), ale ostatecznie tylko jedna lub żadna odpowiedź będzie wynikiem
Podobnie, tylko jedna komórka powinna wyświetlać znacznik wyboru, a pozostałe komórki powinny pozostać niezaznaczone ... w niektórych przypadkach możesz odznaczyć swoją odpowiedź ... Mam nadzieję, że to najlepsza odpowiedź na to pytanie
źródło
Myślę, że łatwiej jest ustawić akcesorium w niestandardowej implementacji UITableViewCell. Szybko użyłem:
override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state accessoryType = selected ? .checkmark : .none }
źródło
Używanie Swift 4.2 i Swift 5 Działający kod znacznika wyboru tylko dla wybranego wiersza w TableView
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { self.tableView.cellForRow(at: indexPath)?.accessoryType = .none } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //print(self.coloursArray[indexPath.row]) self.tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark }
źródło
Zakładając, że należysz do klasy, która dziedziczy
UITableViewController
, to załatwia sprawę w Swift 3:override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // Add a visual cue to indicate that the cell was selected. self.tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark } override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { // Invoked so we can prepare for a change in selection. // Remove previous selection, if any. if let selectedIndex = self.tableView.indexPathForSelectedRow { // Note: Programmatically deslecting does NOT invoke tableView(:didSelectRowAt:), so no risk of infinite loop. self.tableView.deselectRow(at: selectedIndex, animated: false) // Remove the visual selection indication. self.tableView.cellForRow(at: selectedIndex)?.accessoryType = .none } return indexPath }
źródło
mała literówka
// deselect old UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected]; cell.accessoryType = UITableViewCellAccessoryNone; [cell setSelected:FALSE animated:TRUE];
powinien przeczytać
// deselect old UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected]; old.accessoryType = UITableViewCellAccessoryNone; [old setSelected:FALSE animated:TRUE];
a także w
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == [previouslySelected intValue]) { cell.accessoryType = UITableViewCellAccessoryCheckmark; selectedIndex = indexPath; [cell setSelected:YES animated:YES]; } else { cell.accessoryType = UITableViewCellAccessoryNone; [cell setSelected:NO animated:YES]; } }
gdzie poprzednioWybrany jest twój lokalny ivar itp. w ten sposób, jeśli przeładujesz wybrany indeks, zostanie on również odznaczony, gdy będziesz przewijać możliwe wybory.
źródło
Powyższe odpowiedzi nie działają, jeśli ponownie wykorzystałeś komórkę do przechowywania dużej liczby danych. Na przewijaniu możesz zobaczyć powtarzający się znacznik wyboru. Aby uniknąć wykonania poniższych kroków:
zadeklaruj zmienną: var indexNumber: NSInteger = -1
Dodaj poniższy kod w cellforRowAtIndexPath:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ if indexNumber == indexPath.row{ cell.accessoryType = .checkmark }else{ cell.accessoryType = .none } }
A w didselectAtIndexpath dodaj poniższy kod:
override func tableView (_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath as IndexPath)?.accessoryType = .checkmark indexNumber = indexPath.row } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath as IndexPath)?.accessoryType = .none }
źródło
Lepiej spojrzeć na ten problem z innej strony. Przełóż całą pracę na wewnętrzne mechanizmy UIKit i przenieś implementację do UITableViewCell:
@implementation MYTableViewCell - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; self.accessoryType = selected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; } - (void)prepareForReuse { [super prepareForReuse]; self.accessoryType = UITableViewCellAccessoryNone; } @end
źródło
Po prostu
didSelectRowAtIndexPath
wywołaj metodę, gdy wybierzesz dowolny wiersz, aby wyświetlić CheckMark i wybierz wiersz znacznika wyboru, aby ukryć CheckMark.- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:true]; NSLog(@"touch"); UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (cell.accessoryType == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } }
źródło
swift 4 w razie potrzeby.
var lastSelection: NSIndexPath! override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //CHECK MARK THE CELL if self.lastSelection != nil { self.tableView.cellForRow(at: self.lastSelection as IndexPath)?.accessoryType = .none } self.tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark self.lastSelection = indexPath as NSIndexPath self.tableView.deselectRow(at: indexPath, animated: true) }
źródło
Możesz to zrobić na dwa sposoby. jeden jest bez wielu wyborów, a drugi z wieloma wyborami.
// Table View Controller -- without Multiple Selection // Step 1 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if(tableView.cellForRow(at: indexPath)?.imageView?.image == UIImage(systemName:"checkmark.circle")) { tableView.cellForRow(at: indexPath)?.imageView?.image = UIImage(systemName:"circle") } else { tableView.cellForRow(at: indexPath)?.imageView?.image = UIImage(systemName:"checkmark.circle") } } //Step 2 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = employeeValues[indexPath.row] cell.imageView?.image = UIImage(systemName:"circle") return cell } // Table View Controller -- with Multiple Selection @IBOutlet var myTableView: UITableView! override func viewDidLoad() { super.viewDidLoad() self.myTableView.allowsMultipleSelection = true } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = employeeValues[indexPath.row] cell.imageView?.image = UIImage(systemName:"circle") return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // let cell = tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.checkmark tableView.cellForRow(at: indexPath)?.imageView?.image = UIImage(systemName:"checkmark.circle") } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath)?.imageView?.image = UIImage(systemName:"circle") }
źródło
Powyższy kod działa tylko z pojedynczym wyborem . Poniższy kod z pewnością będzie działał dla wielu wyborów .
- (void)viewDidLoad { arrSelectionStatus =[NSMutableArray array]; //arrSelectionStatus holds the cell selection status for (int i=0; i<arrElements.count; i++) { //arrElements holds those elements which will be populated in tableview [arrSelectionStatus addObject:[NSNumber numberWithBool:NO]]; } } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell==nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } cell.textLabel.text=[arrElements objectAtIndex:indexPath.row]; if ([[arrSelectionStatus objectAtIndex:indexPath.row] boolValue] == YES) cell.accessoryType = UITableViewCellAccessoryCheckmark; else cell.accessoryType = UITableViewCellAccessoryNone; return cell; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryCheckmark; [arrSelectionStatus replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:YES]]; } -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryNone; [arrSelectionStatus replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:NO]]; }
źródło
Po ponownym zaznaczeniu wybranej komórki (ze znacznikiem wyboru) po prostu usuń zaznaczenie.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { BOOL isSelected = ([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark); if(isSelected){ [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; [tableView deselectRowAtIndexPath:indexPath animated:YES]; //this won't trigger the didDeselectRowAtIndexPath, but it's always a good idea to remove the selection }else{ [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark; } } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath*)indexPath { [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; }
Premia:
Służy
self.tableView.indexPathForSelectedRow
do wykrywania ścieżki indexPath dla wybranej komórkiźródło
// Check or Uncheck a cell if let cell = tableView.cellForRow(at: indexPath) { if cell.accessoryType == .checkmark { cell.accessoryType = .none } else { cell.accessoryType = .checkmark } }
źródło