53

在我的 tableView 中,我在单元格之间设置了分隔线。我允许选择多个单元格。这是我设置选定单元格背景颜色的代码:

UIView *cellBackgroundColorView = [[UIView alloc] initWithFrame:cell.frame];
[cellBackgroundColorView setBackgroundColor:[UIColor darkGray]];
[cell setSelectedBackgroundView:cellBackgroundColorView];

问题是,如果选择了两个相邻的单元格,则在 iOS7 中它们之间没有分隔线,而在 iOS6 中(如预期的那样)。

我什至尝试将cellBackgroundColorView' 的框架高度设置为 ' cell.frame - 1.0,但这也不起作用。

有任何想法吗?

4

24 回答 24

38

我还没有深入了解它(乍一看,这似乎是一个 iOS 7 错误..),但我找到了一种解决方法。在 tableView:didSelectRowAtIndexPath 中,如果您在下面发送两条消息,则问题在视觉上得到解决(可能会降低性能成本)。

[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

为此(对我而言),deselectRowAtIndexPath:animated: 必须包含动画:YES。用于 reloadRowsAtIndexPaths:withRowAnimation: 的动画无关紧要。

于 2013-10-07T20:33:13.510 回答
28

indexpath的行中添加此代码

cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.backgroundColor = [UIColor clearColor];
于 2013-12-17T10:24:05.980 回答
16

就我而言,我正在为一行制作动画,所以我只需要像这样放置一些:

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

[tableView beginUpdates];
[tableView deselectRowAtIndexPath:indexPath animated:NO]; 
//if you are doing any animation you have deselect the row here inside. 
[tableView endUpdates];
} 
于 2014-12-10T19:48:32.540 回答
12

@samvermette 的回答为我解决了这个问题,但我必须先取消选择选定的行。

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

    //Deselect Row
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];

    // fix for separators bug in iOS 7
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; }
于 2014-04-21T11:46:26.547 回答
7

I encountered this issue when I set my cell's selection style to none programatically, and then when I SELECT my table cells programatically.

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell!
    if tableView == self.jobLevelTableView {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! CheckboxCell

        // for testing purposes
        let checked = true

        // I used M13Checkbox here, in case anybody was wondering
        cell.checkbox.setCheckState(checked ? .checked : .unchecked, animated: false) 

        if checked {
            tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        }

        // CULPRIT
        cell.selectionStyle = .none
        return cell
    }

    cell = UITableViewCell()
    return cell
}

When I set the selection style on the storyboard (and removing the code equivalent), the problem went away!

Storyboard is useful

于 2017-06-28T08:37:22.657 回答
7

将它粘贴到您的 UITableViewCell 类中。

override func layoutSubviews() {
    super.layoutSubviews()

    subviews.forEach { (view) in
        if type(of: view).description() == "_UITableViewCellSeparatorView" {
            view.alpha = 1.0
        }
    }
}
于 2017-11-30T12:17:06.227 回答
4

这个简单的调用是在 iOS 8 上为我完成的。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // ....
    [tableView deselectRowAtIndexPath:indexPath animated:YES]

    // ....
}
于 2014-11-06T23:07:21.693 回答
4

从 iOS 7.0.3 开始,这似乎仍然是一个问题,但我已经用一种简单的方法来伪造分隔符来解决它。

首先将UITableView's 分隔符样式设置为UITableViewCellSeparatorStyleNone. 然后,您可以使用自定义UITableViewCell子类来伪造选定和未选定状态的单元格之间的分隔符:

@implementation MyTableViewCellSubclass

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {

        CGRect frame = self.bounds;
        frame.origin.y = frame.size.height - 1.f;
        frame.size.height = 1.f;

        // Selected background view
        //
        UIView * separatorView = [[UIView alloc] initWithFrame:frame];
        separatorView.backgroundColor = [UIColor darkGrayColor];
        separatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin;

        UIView * selectedView = [[UIView alloc] initWithFrame:self.bounds];
        selectedView.backgroundColor = [UIColor lightGrayColor];
        [selectedView addSubview:separatorView];

        self.selectedBackgroundView = selectedView;

        // Add separator view to content view for unselected state
        //
        UIView * separatorView2 = [[UIView alloc] initWithFrame:frame];
        separatorView2.backgroundColor = [UIColor darkGrayColor];
        separatorView2.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin;

        [self.contentView addSubview:separatorView2];


    }
    return self;
}


@end
于 2013-10-28T21:06:55.557 回答
3

如果您让 iOS 应用其自己的默认选定单元格样式,就会发生这种情况。到目前为止,我发现的最佳解决方法是覆盖选定的属性实现:

在您的单元子类实现中:

    @synthesize selected = _selected;

在初始化方法中:

    // problem actually is caused when you set following 
    // to UITableViewCellSelectionStyleDefault, so:

    [self setSelectionStyle:UITableViewCellSelectionStyleNone]; 

覆盖方法:

    - (BOOL)selected 
    {
        return _selected;
    }
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated 
    {
        _selected = selected
        if (selected) {

            // apply your own selected style

        }
        else {

            // apply your own deselected style

        }
    }
于 2014-08-15T05:48:54.540 回答
2

- cellForRowAtIndexPath

Create two separator views (sv1, sv2)

[cell addsubview:sv1];
[cell.selectedBackgroundView addsubview:sv2];

- didSelectRowAtIndexPath

[tableView deselectRowAtIndexPath:indexPath animated:NO];
于 2014-05-07T12:34:47.433 回答
2

我解决了这个问题(hackishly),不仅重新加载选定的单元格,还重新加载它正上方的单元格。上面的其他解决方案都不适合我。

    NSIndexPath *indexPathOfCellAbove = [NSIndexPath indexPathForRow:(indexPath.row - 1) inSection:indexPath.section];

    if (indexPath.row > 0)
        [self.tableView reloadRowsAtIndexPaths:@[indexPathOfCellAbove, indexPath] withRowAnimation:UITableViewRowAnimationNone];
    else
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
于 2014-01-09T22:22:34.107 回答
2

在 iOS 14 中,Apple 终于减轻了这种痛苦。

如果你想...

  • ...能够选择行(例如在编辑模式下)
  • ...防止默认的灰色或蓝色单元格突出显示颜色
  • ...保留默认的系统分隔符视图

...这会帮助你。在您的UITableViewCell子类中,将其放入初始化程序中:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    // Prevent cell highlighting while preserving selectability and separator views
    if #available(iOS 14.0, *) {
        var backgroundConfig = UIBackgroundConfiguration.listPlainCell()
        backgroundConfig.backgroundColor = .clear
        backgroundConfiguration = backgroundConfig
    } else {
        selectedBackgroundView = {
            let bgView = UIView(frame: .zero)
            bgView.translatesAutoresizingMaskIntoConstraints = false
            bgView.backgroundColor = .clear
            return bgView
        }()
    }
}

如果您只针对 iOS 14+,您可以忽略该else块并完成。如果您还针对 iOS 13 及更低版本,您还需要覆盖layoutSubviews以防止分隔符视图消失(感谢此评论:https ://stackoverflow.com/a/47573308/171933 )。这将解决问题(也在您的UITableViewCell子类中):

override func layoutSubviews() {
    super.layoutSubviews()

    if #available(iOS 14.0, *) {
        // no op
    } else {
        // Setting a custom selectedBackgroundView causes the system to hide the
        // separatorView. If we want to have the separator, we need to show it again.
        subviews.forEach { view in
            if type(of: view).description() == "_UITableViewCellSeparatorView" {
                view.alpha = 1.0
            }
        }
    }
}

享受。

于 2020-10-28T23:10:06.767 回答
1

对我来说,它发生在我以编程方式设置时:

cell.selectionStyle = UITableViewCellSelectionStyleNone;

当我在情节提要中设置此属性时,它可以正常工作。

于 2015-04-27T13:04:35.177 回答
0

单个单元格选择也存在此问题。

另一种解决方案是重新加载表格视图,选择后取消选择:

self.selectedIndex = inIndexPath.row;
[inTableView reloadData];
[inTableView selectRowAtIndexPath:inIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[inTableView deselectRowAtIndexPath:inIndexPath animated:YES];

这消除了我在 Mark 的解决方案中看到的一个微妙的图形选择故障。

于 2013-10-18T02:13:44.057 回答
0

无论如何,这个解决方案不会帮助任何不在他的单元格上使用 backgroundView 的人:

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [cell setBackgroundColor:[UIColor grayColor]];
    }

这样,烦人的视觉效果就大大减少了,而无需重新加载表格。当然,您可以更改grayColor任何可以帮助您改善案例结果的东西

于 2013-11-29T12:17:20.233 回答
0

您也可以尝试将分隔插图设置为 0。我这样做了,它解决了问题,但代价是您失去了插图的美观。

于 2013-10-12T02:19:23.780 回答
0

我所做的是这样的:

  1. 在单元格的内容视图下添加一个新的子视图。
  2. 将其从单元格连接为 selectedBackgroundView。
  3. 添加新选定背景视图的子视图。将其设置为从左侧开始 16 像素并覆盖其余宽度,高 1 像素,从顶部向下 1 像素,背景颜色为 90% 白色。

在我的例子中,我不希望我的行在被选中时被遮蔽,所以我让选中的背景视图保持清晰,但你可以让它变成你喜欢的任何颜色。

另外,我没有使用自动布局,所以只需适当地设置我的尺寸。我认为使用自动布局您必须设置适当的约束。

对我来说,这完全解决了问题(尽管我同意这确实似乎是 ios 7 中的一个错误)。

于 2014-01-17T13:02:54.830 回答
0

用这个:

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = (UITableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
    UIView *selectionColor = [[UIView alloc] init];
    selectionColor.backgroundColor = [UIColor clearColor];
    cell.selectedBackgroundView = selectionColor;
    //71
    UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 71, 320, 2)];//根据需要改变大小,其中-71-y坐标,320-重量,2-高度
  // separatorLineView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"divider_goriz.png"]];//这里也可以放图片
    separatorLineView.backgroundColor = [UIColor redColor];
    [cell.selectedBackgroundView addSubview:separatorLineView];
    返回是;
}
于 2013-12-02T19:54:00.007 回答
0

这里的解决方案对我没有帮助。在大多数情况下,建议删除选择,但我希望单元格保持其选定状态。所以想法是禁用默认分隔线并使用您自己的分隔线。我试过这个,但我遇到了问题(你可以在这里阅读更多关于这个的信息)。accessoryView主要问题是在该地区划线。它只适用于 iOS 8,但我还需要适用于 iOS 7 的解决方案。

我的要求是:

  • 应保留选择
  • 线不应该消失(特别是在单元格被选中的情况下)
  • 所选单元格上方的分隔线也不应该消失

尤其是第三点出现问题,因为 iOS 使用了一种抗锯齿效果来进行上UITableViewCell一个到下一个的交叉。我发现这只发生在 iPad 上。它在每个方向(当前选定的单元格,上方的单元格)上具有大约一个点的大小,因此即使在单元格本身上绘制了一条线(而不是默认使用的),单元格上的一条线也会消失。这条线是在上面的单元格上还是在选定的单元格上没有区别。这种特殊的渲染效果隐藏了我的线条。

解决方案如下所示:

  1. 使用backgroundView绘制两条线的位置:一条在顶部(iPad 的 y 方向 +1 点,iPhone 的 y 方向 0 点)和底部的一条。所以它永远不会被选择效果覆盖。
  2. 创建的背景视图应仅用于选定状态 ( cell.selectedBackgroundView = selectedBackground)。为其他单元格启用默认分隔线。

我在这里发布了一个带有 C# 代码的工作示例,尽管您必须根据需要对其进行调整。现在我的选择问题已经解决了!

于 2014-12-09T15:48:09.903 回答
0

太刺激了,我解决了这个问题。在自定义单元格中添加以下方法调用,并设置颜色分隔符和框架。我将隐藏单元格分隔符,然后在 superview 中自定义负载分隔符上的视图。解决了这个问题的朋友们选择了冲击式分离器

@interface MyCustomTableViewCell(){
   UIView *customSeparatorView;
   CGFloat separatorHight;
}
@property (nonatomic,weak)UIView *originSeparatorView;
@end

-(void)setSeparatorWithInset:(UIEdgeInsets)insets{

if (customSeparatorView) {
    customSeparatorView.frame = CGRectMake(insets.left, insets.top,self.width - insets.left - insets.right, self.originSeparatorView.height-insets.bottom - insets.top);
    self.originSeparatorView.hidden = YES;
    self.originSeparatorView.alpha = 0;
}else{
    for (int i = ([self.contentView.superview.subviews count] - 1); i >= 0; i--) {
        UIView *subView = self.contentView.superview.subviews[i];
        if ([NSStringFromClass(subView.class) hasSuffix:@"SeparatorView"]) {
            self.originSeparatorView = subView;
            subView.hidden = YES;
            subView.alpha = 0;
            subView.frame = CGRectMake(insets.left, insets.top,self.width - insets.left - insets.right, subView.height-insets.bottom - insets.top);

            customSeparatorView = [[subView superview] viewWithTag:separatorViewTag];
            if (!customSeparatorView) {
                customSeparatorView = [[UIView alloc] initWithFrame:subView.frame];

                customSeparatorView.tag = separatorViewTag;
                [[subView superview] addSubview:customSeparatorView];
                customSeparatorView.backgroundColor = [subView backgroundColor];
            }
            [[subView superview] bringSubviewToFront:customSeparatorView];
            break;
        }
    }
  }
}


-(void)setSeparatorColorWithColor:(UIColor *)sepColor{
if (customSeparatorView) {
    customSeparatorView.backgroundColor = sepColor;

    self.originSeparatorView.hidden = YES;
    self.originSeparatorView.alpha = 0;
}else {
    for (int i = ([self.contentView.superview.subviews count] - 1); i >= 0; i--) {
        UIView *subView = self.contentView.superview.subviews[i];
        if ([NSStringFromClass(subView.class) hasSuffix:@"SeparatorView"]) {
           self.originSeparatorView = subView;

            if (sepColor) {
                subView.hidden = YES;
                subView.alpha = 0;
                subView.backgroundColor = sepColor;

                customSeparatorView = [[subView superview] viewWithTag:separatorViewTag];
                if (!customSeparatorView) {
                    customSeparatorView = [[UIView alloc] initWithFrame:subView.frame];

                    customSeparatorView.tag = separatorViewTag;
                    [[subView superview] addSubview:customSeparatorView];
                    customSeparatorView.backgroundColor = [subView backgroundColor];
                }
                [[subView superview] bringSubviewToFront:customSeparatorView];
            }
            break;
        }
    }
  }
}

 -(void)layoutSubviews{
    [super layoutSubviews];
    [self setSeparatorWithInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    [self setSeparatorColorWithColor:[UIColor colorWithRed:31/255.0 green:32/255.0f blue:35/255.0 alpha:0.2]];
 }
于 2015-05-12T07:06:43.797 回答
0

我在IOS 13中遇到了这个问题并以这种方式解决了它:

  1. 在 tableView 单元故事板或 xib 文件中选择选择无

  2. 在单元格覆盖函数的 swift 文件中:

    override func setHighlighted(_ highlighted: Bool, animated: Bool) {
    
        super.setHighlighted(highlighted, animated: animated)
    
        if highlighted {
            contentView.backgroundColor = .lightGray
        } else {
            contentView.backgroundColor = .clear
        }
    }
    

我想像以前的 IOS 版本一样获得常规选择的效果,但是如果您想获得其他东西,请使用您的颜色自定义功能。

于 2019-09-13T07:49:32.727 回答
0

我需要以下内容:

“当用户选择行时,选择背景颜色是透明/白色/无论您如何称呼它,并且分隔线不会消失”

我也在寻找以下问题的解决方案:

“当我在表格(普通表格)中选择一行时,我的选择颜色为灰色,如果我将 cell.selectionStyle 设置为 none -> 单元格之间的分隔符消失了。”

Xcode - 9.2 版本

找到以下解决方案:

  1. 在'tableView(....cellForRowAT...)' let colorView = UIView(frame: CGRect(x: 0.0, y: 3.0, width: cell.frame.width, height: cell.frame.height - 1.0)) colorView.backgroundColor = UIColor.white UITableViewCellClass.appearance().selectedBackgroundView = colorView

UITableViewCellClass - 是您的原型单元格类,它可以将选择颜色更改为白色

  1. 在'tableView(...didSelectRowAt)' cell.selectionStyle = .none

  2. 在 UITableViewCellClass (你的原型单元类)

    覆盖 func layoutSubviews() { super.layoutSubviews()

    subviews.forEach { (view) in
        if type(of: view).description() == "_UITableViewCellSeparatorView" {
            view.alpha = 1.0
        }
    }
    

    }

它允许使用复选标记保留选定的行,并且所有分隔符都已到位。

于 2018-03-30T07:42:33.610 回答
0

为我解决问题的是在 beginUpdates 和 endUpdates 之后重新加载数据:

    private func animateCellHeighChangeForTableView(tableView: UITableView, withDuration duration: Double) {
        UIView.animateWithDuration(duration) { () -> Void in
           tableView.beginUpdates();
           tableView.endUpdates();
           tableView.reloadData();
        }
    }
于 2016-06-04T03:50:39.770 回答
-2

对于那些在 Swift 中寻找解决方案的人,这为我解决了这个问题。在您的cellForRowAtIndexPath方法中,调用后dequeueReusableCellWithIdentifier,您只需将单元格设置selectionStyle.None

这是代码:

    override func tableView(tableView: UITableView?,  cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:TextTableViewCell = tableView!.dequeueReusableCellWithIdentifier("textCell", forIndexPath: indexPath) as! TextTableViewCell

    cell.selectionStyle = .None //  This fixes the disappearing border line issue
于 2015-10-08T15:27:52.720 回答