在iOS7中选择单元格时,UITableView分隔线消失

时间:2013-10-06 18:38:47

标签: uitableview ios7

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

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

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

我甚至尝试将cellBackgroundColorView的帧高设置为cell.frame - 1.0的帧高,但这也不起作用。

有什么想法吗?

24 个答案:

答案 0 :(得分:37)

我还没有深究它(乍一看它似乎是一个iOS 7的bug ...),但我找到了一个解决方法。在tableView:didSelectRowAtIndexPath中,如果您发送以下两条消息,则可以直观地解决问题(可能的性能成本)。

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

为了这个(对我来说),deselectRowAtIndexPath:animated:必须包含动画:YES。用于reloadRowsAtIndexPaths:withRowAnimation:的动画无关紧要。

答案 1 :(得分:24)

indexpath

的行的单元格中添加此代码
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.backgroundColor = [UIColor clearColor];

答案 2 :(得分:15)

在我的情况下,我动画了一行,所以我只需要这样做:

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

答案 3 :(得分:12)

@ samvermette answer为我解决了这个问题,但我不得不首先取消选择所选的行。

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

答案 4 :(得分:5)

当我以编程方式将单元格的选择样式设置为无,然后以编程方式选择表格单元格时,我遇到了此问题。

    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
}

当我在故事板上设置选择样式(并删除相应的代码)时,问题就消失了!

Storyboard is useful

答案 5 :(得分:4)

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

首先将UITableView的分隔符样式设置为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

答案 6 :(得分:4)

这个简单的调用在iOS 8上为我做了。

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

    // ....
}

答案 7 :(得分:3)

在你的UITableViewCell类中过去它。

override func layoutSubviews() {
    super.layoutSubviews()

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

答案 8 :(得分: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

        }
    }

答案 9 :(得分:2)

我通过不仅重新加载选定的单元格而且重新加载正上方的单元格来解决这个问题(黑客)。上述其他解决方案都不适用于我。

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

答案 10 :(得分:2)

- cellForRowAtIndexPath

Create two separator views (sv1, sv2)

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

- didSelectRowAtIndexPath

[tableView deselectRowAtIndexPath:indexPath animated:NO];

答案 11 :(得分:1)

对我来说,这是在我以编程方式设置的时候发生的:

stopService(i)

当我在故事板中设置此属性时,它可以正常工作。

答案 12 :(得分:0)

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

享受。

答案 13 :(得分:0)

我在IOS 13上遇到了这个问题,并以此方式解决了该问题:

  1. 在tableView单元情节提要中或xib文件中,选择“无选择”

  2. 在单元格的快速文件中覆盖func:

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

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

答案 14 :(得分:0)

我需要以下内容:

  

"当用户选择行时,选择背景颜色为   透明/白色/无论你怎么称呼它和分隔线都没有   消失"

我对以下问题的解决方案也很满意:

  

"当我在表格中选择一行(普通类型表格)时,我有选择权   颜色为灰色,如果我将cell.selectionStyle设置为none - >分离器   细胞之间消失了。"

Xcode - 9.2版

找到以下解决方案:

  1. in 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
  2. UITableViewCellClass - 是您的原型单元类 它可以将选择颜色更改为白色

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

    2. UITableViewCellClass(您的原型单元类)中的
    3. 覆盖func layoutSubviews(){     super.layoutSubviews()

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

      }

    4. 它允许选中的行带有复选标记,并且所有分隔符都已到位。

答案 15 :(得分:0)

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

namespace StackOverFlow
{
    class Program
    {
        static void Main(string[] args)
        {
            ObjectBuilder<string> stringObjectBuilder = new ObjectBuilder<string>();
            Collection<string> stringCol = stringObjectBuilder.Build();
            foreach (string s in stringCol) Console.WriteLine(s);
            ObjectBuilder<double> doubleObjectBuilder = new ObjectBuilder<double>();
            Collection<double> doubleCol = doubleObjectBuilder.Build();
            foreach (double d in doubleCol) Console.WriteLine(d);
            Console.ReadKey();

        }
    }
    public class ObjectBuilder<T>
    {
        private object _collectionModelType;
        //private Type_collectionModelType;
        public ObjectBuilder()
            {

            }

        public Collection<T> Build()
        {
            //_collectionModelType = collectionTypeToBuild;
            var x = CreateCollection();
            return x;
        }


        //helper
        private Collection<T> CreateCollection()
        {
            Collection<T> objCol = new Collection<T>();
            objCol.Add(default(T));
            return  objCol;
        }
    }
}

答案 16 :(得分: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]];
 }

答案 17 :(得分:0)

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

我的要求是:

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

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

解决方案如下所示:

  1. 使用cell.selectedBackgroundView = selectedBackground绘制两条线:一条在顶部(iPad的y方向+1点,iPhone的y方向0点),底部的一条。所以它永远不会被选择效果所覆盖。
  2. 创建的背景视图应仅用于选定状态({{1}})。为其他单元格启用了默认分隔线。
  3. 我有一个C#代码发布here的工作示例,但您必须根据自己的需要进行调整。现在我的选择问题已经消失了!

答案 18 :(得分:0)

我做的是:

  1. 在单元格的内容视图下添加新的子视图。
  2. 将其作为selectedBackgroundView从单元格连接。
  3. 添加新选定背景视图的子视图。将其设置为从左侧开始16px并覆盖其余宽度,高1px,从顶部向下1px,背景颜色为90%白色。
  4. 在我的情况下,我在选择时根本不想让我的行显示为阴影,所以我将选定的背景视图保持清晰,但你可以将它设为任意颜色。

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

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

答案 19 :(得分: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)];/// change size as you need, where - 71 - y coordinate, 320 - weight, 2 - height
  //  separatorLineView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"divider_goriz.png"]];// you can also put image here
    separatorLineView.backgroundColor = [UIColor redColor];
    [cell.selectedBackgroundView addSubview:separatorLineView];
    return YES;
}

答案 20 :(得分:0)

无论如何,这个解决方案不会帮助那些没有在他的手机上使用backgroundView的人:

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [cell setBackgroundColor:[UIColor grayColor]];
    }
这样就可以大大减少令人讨厌的视觉效果,而无需重新加载表格。 当然,您可以使用任何可以帮助您改善案例结果的内容来更改grayColor

答案 21 :(得分:0)

单细胞选择也存在这个问题。

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

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

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

答案 22 :(得分:0)

你也可以尝试将分隔符插入设置为0.我这样做了它解决了问题,但是权衡的是你丢失了插图的漂亮外观。

答案 23 :(得分:-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