22

我在滚动表格时遇到表格视图单元格未保持其“选定”状态的问题。以下是相关代码:

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

对于细胞:

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

如何让选定的单元格保持突出显示?如果我将它从屏幕上滚动出来,当它在屏幕上回滚时,它会以未选中状态出现(隐藏了它的 selectedBg)。

编辑:从单元格中删除 setHighlighted 方法可以解决问题。然而,这意味着按下表格单元格时我没有突出显示状态。我想知道这个问题的解决方案。

4

12 回答 12

14

有同样的问题,选定单元格的附件视图在滚动时消失了。我的同事发现了这个问题的好方法。原因是在 iOS 7 on touchesBegan事件 UITableView 取消选择选定的单元格并选择按下的单元格。在 iOS 6 中它不会发生,并且在滚动选定的单元格时保持选中状态。要在 iOS 7 中获得相同的行为,请尝试:

1) 在您的 tableView 中启用多项选择。

2) 转到 tableView 委托方法didSelectRowAtIndexPath,并用代码取消选择单元格:

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

解决了我的问题!希望它会有所帮助,对不起我的英语不好顺便说一句。

于 2013-10-30T14:30:28.060 回答
8

我知道我的方法不是很正统,但似乎有效。这是我的解决方案:

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

您还必须实现您在帖子中提到的所有方法(@soleil)

于 2014-11-30T20:13:14.057 回答
3

我正在使用 Xcode 9.0.1 和 Swift 4.0。当单元格离开屏幕并返回时,我发现以下代码解决了我的选择标记:

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if cell.isSelected {
        cell.accessoryType = .checkmark
    } else {
        cell.accessoryType = .none
    }
}
于 2017-11-06T18:12:01.897 回答
2

iOS 7/8 都在滚动开始时取消选择单元格(正如 Alexander Larionov 指出的那样)。

对我来说更简单的解决方案是在我的 ViewController 中实现这个 UIScrollViewDelegate 方法:

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

这是因为我的 viewController 是 UITableView 的委托,而 UITableView 继承自 UIScrollView。

于 2015-01-29T23:36:53.830 回答
1

如果你想在 Swift 中实现同样的目标,那么这里是代码。顺便说一句,我将 Xcode 7.2 与 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
    }
}

做任何你想做的其他定制..

谢谢..

希望这有帮助。

于 2016-01-24T09:14:06.147 回答
1

Swift 3 解决方案,2017 年。

我用这行简单的代码解决了这个问题:

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

tableView(tableView:cellForRowAt indexPath:)方法内部:

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()
}
于 2017-07-20T16:55:26.267 回答
1

斯威夫特 5

将以下代码放入您的自定义UITableViewCell子类中:

override func setHighlighted(_ highlighted: Bool, animated: Bool) {
    guard !isSelected else { return }

    super.setHighlighted(highlighted, animated: animated)
    if highlighted {
        // Style cell for highlighted
    } else {
        // Style cell for unhighlighted
    }
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    if selected {
        // Style cell for selected
    } else {
        // Style cell for unselected
    }
}

说明:尝试在setHighlighted和上设置断点setSelected。您会发现该方法按此顺序dequeueReusableCell调用setSelected以重置新单元格。因此,您的突出显示代码正在破坏您在选择代码中所做的样式。非黑客修复是避免在被调用时破坏您选择的样式。setHighlighted setHighlighted(false, animated: false)

于 2019-06-08T23:55:12.530 回答
0

您是否尝试过比较索引路径的行而不是整个索引路径对象?

if ((indexPath.row == self.selectedIndexPath.row) && (indexPath.section == self.selectedIndexPath.section)) {
    [cell setSelected:YES animated:NO];
}
于 2012-11-07T18:03:19.343 回答
0

这是我想出的解决方案——它甚至不会让人觉得很奇怪。

1)在滚动期间实现-scrollViewWillBeginDragging:-scrollViewWillEndDragging:withVelocity:targetContentOffset:手动突出显示所选行(如果有)的单元格。

我的看起来像这样:

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

scrollViewIsDragging属性在那里,因此-tableView:cellForRowAtIndexPath:我们可以确保任何新出列的单元格具有适当的突出显示(例如,如果所选行的单元格在离开屏幕后滚动到屏幕上)。该方法的相关部分如下所示:

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

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

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

}

......你有它。selectedRow 的单元格将在滚动期间保持突出显示。

于 2014-05-31T01:55:17.263 回答
0

UITableViewCell 有一个 BOOL 属性“ selected ”。每当您加载单元格时,请检查 selected 的状态并在 cellForRowAtIndexPath 定义中相应地进行选择或取消选择:

if (cell.selected) {
    // Maintain selected state
}
else{
     // Maintain deselected state
}
于 2015-02-18T16:32:30.133 回答
0

在这里发布了一个快速的答案: https ://stackoverflow.com/a/35605984/3754003

在其中,我还解释了为什么会发生这种情况。

于 2016-02-24T15:21:54.467 回答
0

不要使用内置系统属性isSelected

您可以创建自己的属性,例如:

var isSelectedStyle = false
cell.isSelectedStyle = ....
于 2021-10-22T08:46:07.137 回答