开发者

UITableViewCell Accessory Type Checked on Tap & Set other unchecked

I am confused a little bit about settings table view cell accessories.

I have fixed two sections in my table

  • Home
  • Office

What I want is as follow....

  • When User tap any of the cell
  • Cell gets selected &
    • I want to set checked (set uitableviewcell accessory type -checked of tapped cell )
  • And also all other cell's accessory type now should set to
    • uitable view cell accessory type none

I have tried following code. But I found that indexpath.row & indexpath.section is readonly properties.

// Override to support row selection in the table view.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    
    [tblProfileView deselectRowAtIndexPath:indexPath animated:YES];
    int i,max;
    UITableViewCell *x; NSIndexPath *tt;

    for(i=0;i<[tblProfileView numberOfRowsInSection:0];i++)
    {
        tt.row=i; tt.section=0;
        x=[tblProfileView cellForRowAt开发者_如何学JAVAIndexPath:];
        [x setAccessoryType:UITableViewCellAccessoryNone];
    }
    for(i=0;i<[tblProfileView numberOfRowsInSection:1];i++)
    {
        tt.row=i; tt.section=1;
        x=[tblProfileView cellForRowAtIndexPath:tt];
        [x setAccessoryType:UITableViewCellAccessoryNone];
    }

    x=[tblProfileView cellForRowAtIndexPath:indexPath];
    [x setAccessoryType:UITableViewCellAccessoryCheckmark];
    // Navigation logic may go here -- for example, create and push another view controller.
    // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
    // [self.navigationController pushViewController:anotherViewController animated:YES];
    // [anotherViewController release];
}


I would keep track of the data that should be checked and change the cell in tableView:didSelectRowAtIndexPath: and update which data is checked in tableView:cellForRowAtIndexPath: like this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // do usual stuff here including getting the cell

    // determine the data from the IndexPath.row

    if (data == self.checkedData)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // determine the selected data from the IndexPath.row

    if (data != self.checkedData) {
       self.checkedData = data;
    }

    [tableView reloadData];
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];

    if (newCell.accessoryType == UITableViewCellAccessoryNone) {
        newCell.accessoryType = UITableViewCellAccessoryCheckmark;
    }else {
        newCell.accessoryType = UITableViewCellAccessoryNone;
    }


}

also you need to remove the checkmark accessory on cellForRowAtIndexPath

if ([selectedOptionsArray indexOfObject:cell.textLabel.text] != NSNotFound) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
    cell.accessoryType = UITableViewCellAccessoryNone;
}


Declare one int variable named prev and implement this method:-

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

 UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];

   if (cell.accessoryType==UITableViewCellAccessoryNone) 
   {
      cell.accessoryType=UITableViewCellAccessoryCheckmark;
      if (prev!=indexPath.row) {
         cell=[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:prev inSection:0]];
         cell.accessoryType=UITableViewCellAccessoryNone;
         prev=indexPath.row;
     }

 }
 else{
     cell.accessoryType=UITableViewCellAccessoryNone;
 }
}


A shortest and easiest way to implement logic for checkmark in selected row only.....


1.Create a global object of NSIndexPath..

selectedIndexPathForCheckMark= [[NSIndexPath alloc] init];

2.In didSelectRowAtIndexPath..

//Assiging selected indexPath to the declared object

selectedIndexPathForCheckMark = indexPath;  
[tableView reloadData];

3.in cellForRowAtIndexPath..

if ([selectedIndexPathForCheckMark isEqual:indexPath]) {
    [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else {
    //setAccessoryType None if not get the selected indexPath
    [cell setAccessoryType:UITableViewCellAccessoryNone];
}


Here's how I do it with static cells, and bypassing cellForRow

Create a var that stores the location of the "checked" cell.

 NSInteger _checkedCell;

Then just implement willDisplayCell and didSelectRow methods like this.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (_checkedCell == indexPath.row) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    _checkedCell = indexPath.row;
    [self.tableView reloadData];
}


I known this question is quite old, but here is the Swift version based on Blackberry's response (which I've voted up by the way)

import UIKit

class PlacesViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {

    var placesArray = NSMutableArray()
    
    var previousCheckedIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.placesArray.addObject("Tandil")
        self.placesArray.addObject("Balcarce")
        self.placesArray.addObject("Mar del Plata")
        
        self.tableView.rowHeight = UITableViewAutomaticDimension
    }

    
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.placesArray.count
    }
    
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell

        cell.textLabel?.text = self.placesArray.objectAtIndex(indexPath.row) as? String
        

        return cell
    }
    
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        if (indexPath.row != previousCheckedIndex) {
            var cell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
            if (cell.accessoryType == UITableViewCellAccessoryType.None) {
                cell.accessoryType = UITableViewCellAccessoryType.Checkmark
                if (previousCheckedIndex != indexPath.row) {
                    cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: previousCheckedIndex, inSection: 0))!
                    cell.accessoryType = UITableViewCellAccessoryType.None
                    previousCheckedIndex = indexPath.row
                }
            } else {
                cell.accessoryType = UITableViewCellAccessoryType.None
            }
        
            tableView.reloadData()
        }
    }
}


In Swift 2.0 using custom accessoryView uitableviewcell with swift

1º Creating Globar var IndexPath

var indexSelected = NSIndexPath()

2º In didSelectRowAtIndexPath

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        indexSelected = indexPath
        TB_Lojas.reloadData()
    }

3º in cellForRowAtIndexPath:

if SelectedIndexPath == indexPath {
                let img = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
                img.image = UIImage(named: "check")
                cell.accessoryView = img
            }else{
                let img = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
                img.image = UIImage(named: "uncheck")
                cell.accessoryView = img
            }
}


Considering you only want to maintain a single selection, and if you have a custom UITableViewCell, I would recommend the following.

In your UITableViewController

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    //... 
    let data = dataArray[indexPath.row]
    if data.isSelected {
        tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)
    }
    //...

    return cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let data = dataArray[indexPath.row]
    data.isSelected = true
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    cell?.setSelected(true, animated: true)
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    let data = dataArray[indexPath.row]
    data.isSelected = false
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    cell?.setSelected(false, animated: true)
}

In the custom UITableViewCell

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

    // Configure the view for the selected state
    self.accessoryType = .None
    if selected {
        self.accessoryType = .Checkmark
    }
}

As long as allowsMultipleSelection is not enabled, it will automatically handle deselecting other cells when a new one is selected. If allowMultipleSelection is enabled, then it will work as well, except you will just need to tap again to deselect.


BlackBerry's answer in Swift 3. UITableView with standard cells, selecting 0 or 1 cells.

private var previousSelection = NSIndexPath()

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    let cell = tableView.cellForRow(at: indexPath)!
    if cell.accessoryType == .none {
        cell.accessoryType = .checkmark
        selection = indexPath

        if previousSelection == IndexPath() {
            previousSelection = indexPath
        } else if previousSelection != indexPath {
            let previousCell = tableView.cellForRow(at: previousSelection)
            previousCell?.accessoryType = .none
            previousSelection = indexPath
        }
    } else if cell.accessoryType == .checkmark {
        cell.accessoryType = .none
        selection = IndexPath()
    }

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜