✔ Centang baris yang dipilih di UITableViewCell

93

Saya seorang pemula pengembangan iOS. Saya ingin menambahkan tanda centang ke my UITableViewCellketika dipilih. Tanda centang harus dihapus ketika baris lain dipilih. Bagaimana saya melakukan ini?

Suchi
sumber

Jawaban:

206

Jangan gunakan [tableview reloadData]; // itu palu.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath   *)indexPath
{
    [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}

-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
Ujwal Manjunath
sumber
6
Bagaimana jika saya hanya menginginkan tanda centang dan ingin membatalkan pilihan baris setelah pemilihan?
gyozo kudor
itu memilih baris indeks yang sama di setiap bagian @Ujwal Manjunath
bLacK hoLE
1
- (void) reloadData seharusnya relatif murah, menurut dokumen. Namun demikian, ini lebih menyenangkan secara semantik.
MattD
Mengapa Anda tidak menggunakan '[tableview reloadData]'? Saya ingin menggunakan multiselect di tableview saya. Saya menggunakan objek yang diterima dari server untuk mengatur tanda centang di sel tableview saya. Sekali, saya melakukannya, saya menyimpan objek cek dalam larik global. Namun, ketika saya menggunakan array itu untuk membandingkan di dalam metode 'didSelectRowAtIndexPath' saya untuk melihat apakah indexpath cocok dengan objek ini di dalam array global saya. Saya tidak dapat menemukannya. Saya pikir itu adalah [tableView reloadData]. Bagaimana menurut Anda? Mohon saran.
Ron
1
Jawaban di atas tidak berfungsi jika Anda menggunakan kembali sel untuk sejumlah besar data. Saat scroll, Anda dapat melihat tanda centang berulang. Periksa solusi saya stackoverflow.com/questions/7982944/…
Dishant
81

Dalam metode UITableViewDatasource Anda:

- (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];
}

Dan lastIndexPath adalah property(strong) NSIndexPath* lastIndexPath;

0x8badf00d
sumber
22

Saya menemukan bahwa memuat ulang data mengganggu animasi batal pilih dengan cara yang jelek.

Implementasi Swift ini dengan rapi menambahkan / menghapus tanda centang dan membatalkan pilihan baris:

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)
}

dimana lastSelectiondideklarasikan sebagaivar lastSelection: NSIndexPath!

Tidak perlu aktivitas ekstra cellForRowAtIndexPath. Seharusnya tidak sulit untuk ditiru di Obj-C.

Harry Nelken
sumber
12

Untuk mengatur tanda centang:

UITableViewCell *cell = ...;
cell.accessoryType = UITableViewCellAccessoryCheckmark;

Untuk memilih / membatalkan pilihan sel:

[cell setSelected:TRUE animated:TRUE]; // select
[cell setSelected:FALSE animated:TRUE]; // deselect

Untuk membatalkan pilihan sel sebelumnya, gunakan ivar NSIndexPath * lastSelected untuk melacak sel yang terakhir dipilih:

- (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;
}
Jano
sumber
8

Perbarui 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
    }
Puji Wahono
sumber
7
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
    }

}

berdasarkan tampilan tabel dataArray dibentuk .. demikian pula, saya mengambil array kosong, dan setiap kali pengguna mengetuk sel, berdasarkan indexValue dari dataArray saya menyimpan objek itu di selectedDataArray

Adapun pertanyaannya seperti ... Sebuah pertanyaan memiliki banyak pilihan (Answers), Tetapi pada akhirnya hanya satu atau tidak ada jawaban yang akan menjadi hasil

masukkan deskripsi gambar di sini

Demikian juga, hanya satu sel yang harus menunjukkan tanda centang dan sel yang tersisa harus tidak dipilih ... dalam beberapa kasus Anda dapat membatalkan pilihan jawaban Anda ... Saya harap ini adalah jawaban terbaik untuk pertanyaan ini

masukkan deskripsi gambar di sini

Singam madhukar
sumber
Baris pertama ini masih belum diformat sebagai kode. Gunakan interpunctation!
buhtz
6

Saya pikir lebih bersih untuk mengatur aksesori dalam implementasi UITableViewCell kustom Anda. Dengan cepat, saya telah menggunakan:

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
    accessoryType = selected ? .checkmark : .none
}
Don Miguel
sumber
1
Jawaban ini diremehkan secara pidana.
WaaleedKhan
Terima kasih @WaaleedKhan
Don Miguel
4

Menggunakan Swift 4.2 dan swift 5 Kode kerja tanda centang hanya untuk baris yang dipilih di 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
}
M Murteza
sumber
3

Dengan asumsi Anda berada di kelas yang mewarisi dari UITableViewController, ini melakukan trik di 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
}
Janus Varmarken
sumber
2

kesalahan ketik kecil

// deselect old
UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected];
cell.accessoryType = UITableViewCellAccessoryNone;
[cell setSelected:FALSE animated:TRUE];

harus dibaca

// deselect old
UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected];
old.accessoryType = UITableViewCellAccessoryNone;
[old setSelected:FALSE animated:TRUE];

dan juga di

- (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];
    }
} 

di mana beforeSelected adalah ivar lokal Anda, dll. Dengan cara itu jika Anda memuat ulang dengan indeks yang dipilih, pilihan itu juga akan dibatalkan ketika Anda membolak-balik pilihan yang mungkin.

Morf
sumber
2

Jawaban di atas tidak berfungsi jika Anda menggunakan kembali sel untuk sejumlah besar data. Saat scroll, Anda dapat melihat tanda centang berulang. Untuk menghindari penggunaan langkah-langkah di bawah ini:

  1. deklarasikan pada variabel: var indexNumber: NSInteger = -1

  2. Tambahkan kode di bawah ini di cellforRowAtIndexPath:

     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{         
           if indexNumber == indexPath.row{
               cell.accessoryType = .checkmark
           }else{
               cell.accessoryType = .none
           }
    }
    
  3. Dan di didselectAtIndexpath tambahkan kode di bawah ini:

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
}
Dishant
sumber
2

Lebih baik menghadapi masalah ini dari arah lain. Letakkan semua pekerjaan pada mekanisme UIKit internal dan pindahkan implementasi ke 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
Al Zonke
sumber
1

Cukup Panggil didSelectRowAtIndexPathMetode saat memilih baris apa pun untuk Tampilkan Tanda Check dan Pilih baris tanda centang untuk menyembunyikan Tanda Periksa

- (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;
    }
}
Priyank Jotangiya
sumber
1

swift 4 jika Anda membutuhkan.

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)

}
pembuat kode
sumber
1

Ada dua cara untuk melakukannya. satu tanpa banyak pilihan dan satu lagi dengan banyak pilihan.

// 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")  
}
Mirza Q Ali
sumber
0

Kode yang disebutkan di atas hanya berfungsi dengan satu pilihan . Kode berikut ini pasti akan berfungsi untuk banyak pilihan .

- (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]];
}
Polandia
sumber
0

Ketika sel yang dipilih (dengan tanda centang dipilih lagi), hapus saja seleksi.

- (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;
}

Bonus:

Gunakan self.tableView.indexPathForSelectedRowuntuk mendeteksi indexPath untuk sel yang dipilih

Kesong Xie
sumber
0
// Check or Uncheck a cell 
        if let cell = tableView.cellForRow(at: indexPath) {
            if cell.accessoryType == .checkmark {
                cell.accessoryType = .none
            } else {
                cell.accessoryType = .checkmark
            }
        }

Teja Goud Kandula
sumber