在iOS 7上的UITableViewCell之间绘制自定义分隔线

在iOS 7上的UITableViewCell之间绘制自定义分隔线,ios,uitableview,autolayout,nslayoutconstraint,Ios,Uitableview,Autolayout,Nslayoutconstraint,因为在UITableViewCell之间使用默认分隔线时遇到了一些问题,所以我想使用自己的分隔线。因此,我使用自动布局。C是我使用的语言。当然,您可以在Objective-C中提供解决方案 在自定义单元格的构造函数中,我添加了视图UIView: 必须将其添加到superview中,否则它无法覆盖附件区域。在updateConstraints中,我设置了约束: separator.TranslatesAutoresizingMaskIntoConstraints = false; this.Co

因为在UITableViewCell之间使用默认分隔线时遇到了一些问题,所以我想使用自己的分隔线。因此,我使用自动布局。C是我使用的语言。当然,您可以在Objective-C中提供解决方案

在自定义单元格的构造函数中,我添加了视图UIView:

必须将其添加到superview中,否则它无法覆盖附件区域。在updateConstraints中,我设置了约束:

separator.TranslatesAutoresizingMaskIntoConstraints = false;

this.ContentView.Superview.AddConstraints (NSLayoutConstraint.FromVisualFormat ("H:|[separator]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
this.ContentView.Superview.AddConstraints (NSLayoutConstraint.FromVisualFormat ("V:|-(82@999)-[separator(1)]|", (NSLayoutFormatOptions)0, null, viewsDictionary));

例如,这在iOS 8上有效,但在iOS 7上无效。此外,这个约束V:[separator1]|在iOS 8上有效,但在iOS 7上无效。

据我所知,我想到了两种可能的方法来解决这个问题:

不使用默认的附件视图,而完全不使用附件视图。相反,通过创建视网膜显示辅助视图屏幕截图所需的图像或使用自定义图像或其本身来伪造辅助视图。如果您有假附件视图,可以将其添加到contentView中,并使用相应的约束对其进行定位。 现在,您可以在禁用TableView.SeparatorStyle=UITableViewCellSeparatorStyle.None;的默认分隔符的同时向内容视图添加一行;。但是您必须向保存图像的已创建UIButton添加事件,因为AccessoryButtonTapped将不再被调用。这是许多只用于添加分隔线的步骤

在背景视图上添加分隔线。这就是我采取的方法

首先是GradientView类,该类使用分隔线创建渐变背景视图:

public class GradientView : UIView
{
    // accessors
    private CAShapeLayer line;
    private bool shouldShowSeparatorLine = false;

    private CAGradientLayer gradientLayer {
        // read-only
        get { return (CAGradientLayer)this.Layer; }
    }

    public CGColor[] Colors {
        // set the colors of the gradient layer
        get { return this.gradientLayer.Colors; }
        set { this.gradientLayer.Colors = value; }
    }

    public GradientView(bool shouldShowSeparatorLine = false)
    {
        this.shouldShowSeparatorLine = shouldShowSeparatorLine;

        this.BackgroundColor = UIColor.Clear;
    }

    [Export ("layerClass")]
    public static Class LayerClass ()
    {
        // use a different Core Animation layer for its backing store
        // normally a CALayer is used for a UIView
        return new Class (typeof(CAGradientLayer));
    }


    public override void Draw (RectangleF rect)
    {
        base.Draw (rect);

        if (shouldShowSeparatorLines) {

            // get graphics context
            CGContext context = UIGraphics.GetCurrentContext ();

            context.SetStrokeColor(UIColor.FromRGB (21,66,139).CGColor);
            context.SetLineWidth (1.0f);
            context.SetShouldAntialias (false);

            float top = 0;
            if (Util.UserInterfaceIdiomIsPhone) {
                top = 0;
            } else {
                top = 1;
            }

            // top
            // start point
            context.MoveTo (0, top);
            // end point
            context.AddLineToPoint (rect.Width, top);
            // draw the path
            context.DrawPath (CGPathDrawingMode.Stroke);

            // bottom
            // start point
            context.MoveTo (0, rect.Height);
            // end point
            context.AddLineToPoint (rect.Width, rect.Height);
            // draw the path
            context.DrawPath (CGPathDrawingMode.Stroke);
        }
    }
您不需要两条分隔线,但对于我的选择问题,我需要两条分隔线

在自定义UITableViewCell中,相应地在初始值设定项中设置背景:

GradientView background = new GradientView (true);
background.Colors = new CGColor[] {
    UIColor.White.CGColor,
    UIColor.White.CGColor,
    UIColor.Blue.CGColor
};

this.BackgroundView = background;

当然,你不需要梯度的东西,所以你可以忽略它。GradientView将只包含带有几个字段的绘图方法。

此代码适用于UITableViewCell的子类:

- (void)awakeFromNib {
    // Initialization code
    [super awakeFromNib];
    PCTableViewCellSeparatorView *sV = [[PCTableViewCellSeparatorView alloc] initWithFrame:CGRectMake(0, 0, 0, 1.0)]; // my custom subclass of UIView for drawing 1px line
    sV.backgroundColor = [UIColor clearColor];
    self.accessoryView.backgroundColor = [UIColor clearColor];
    [sV setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.contentView addSubview:sV];
    // horizontal
    NSNumber *space     = [NSNumber numberWithFloat:0.0f];
    NSNumber *space2    = [NSNumber numberWithFloat:-64.0f]; // MAGIC HERE
    NSDictionary *views = NSDictionaryOfVariableBindings(sV, self.contentView);
    NSDictionary *metrics = NSDictionaryOfVariableBindings(space, space2);
    NSString *horizontalFormat =@"|-space-[sV]-space2-|";
    NSArray* horizontal = [NSLayoutConstraint constraintsWithVisualFormat:horizontalFormat                                                              options:NSLayoutFormatDirectionLeadingToTrailing
                                                              metrics:metrics
                                                                views:views];
    // height
    NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:sV attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:1.0f];
    // bottom
    NSLayoutConstraint *vertical1 = [NSLayoutConstraint constraintWithItem: sV
                                                             attribute: NSLayoutAttributeBottom
                                                             relatedBy: NSLayoutRelationEqual
                                                                toItem: self.contentView
                                                             attribute: NSLayoutAttributeBottom
                                                            multiplier: 1.0f
                                                              constant: 0.0f
                                 ];
    [self.contentView addConstraints:horizontal];
    [self.contentView addConstraints:@[vertical1,height]];
    self.separatorView = sV; // my own cell's property
}
PCTableViewCellSeparatorView的代码:

#import <UIKit/UIKit.h>
@interface PCTableViewCellSeparatorView : UIView

@end

#import "PCTableViewCellSeparatorView.h"
#import "UIColor+Utilities.h"

@implementation PCTableViewCellSeparatorView

// -----------------------------------------------------------------------
#pragma mark - Drawing
// -----------------------------------------------------------------------
- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    CGFloat inset;
    switch ([UIScreen screenScale]) {
        case ScreenScale2x:
            inset = 0.5f/2.0f;
            break;
        case ScreenScale3x:
            inset = 0.5f/3.0f;
            break;
        default:
            inset = 0.5f;
            break;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    // draw
    CGContextSetLineWidth(context, inset);
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithRGB:PCColorGrey].CGColor);
    CGContextMoveToPoint(context, 0, CGRectGetHeight(rect)-inset);
    CGContextAddLineToPoint(context, CGRectGetWidth(rect), CGRectGetHeight(rect)-inset);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);
}

@结束

您只需要在contentView中添加子视图。我认为,在iOS 7上,contentView是不透明的。或者子视图无法添加到单元格的视图中…但contentView不占用单元格的整个宽度。不包括其他零件附件视图。我试图将我的线路也添加到accessoryView,但应用程序崩溃了。iOS 7上似乎没有contentView的父级。另一个想法是在contentView中添加与指示器相同的自定义图像,并在触摸时做出反应。另一个想法是在背景视图中添加线条。PCTableViewCellSeparatorView是什么样子的?因此,您要在contentView上添加一个单独的视图,并将其放置在底部,高度为1。您需要该单元的属性做什么?为什么需要-64.0f?是否将分隔符放入accessoryView区域?如果苹果改变尺寸呢?我得试试你的解决方案,看看它在任何情况下是否都有效。目前我有一个解决方案,但如果真的有效,我必须尝试一下。否则,如果我有时间,我将研究您的解决方案。@使用自定义drawRect测试自定义视图类PCTableViewCellSeparatorView:UIView。我需要单元格的属性来设置分隔符颜色-64.0f–此约束有助于在单元格外部绘制线,上部辅助视图。也许这不是一个完美的解决方案,但我在iPad和iPhone上测试了它——它现在可以工作了。啊,正如我所想。如果不是太大的话,也许你可以在答案中加入PCTableViewCellSeparator视图。感谢您提供另一种方法/解决方法。正如我说的,如果我有时间,我会研究你的解决方案。目前,我正在与其他iOS错误作斗争…@测试我做到了。我为UIScreen使用了一个类别,但它是[UIScreen mainScreen]的简单界面包装器。scale@testing哦,今天我发现,我的实现自定义分隔符视图阻止了单元格的自动布局计算。请继续收看,我会尽力解决的。
#import <UIKit/UIKit.h>
@interface PCTableViewCellSeparatorView : UIView

@end

#import "PCTableViewCellSeparatorView.h"
#import "UIColor+Utilities.h"

@implementation PCTableViewCellSeparatorView

// -----------------------------------------------------------------------
#pragma mark - Drawing
// -----------------------------------------------------------------------
- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    CGFloat inset;
    switch ([UIScreen screenScale]) {
        case ScreenScale2x:
            inset = 0.5f/2.0f;
            break;
        case ScreenScale3x:
            inset = 0.5f/3.0f;
            break;
        default:
            inset = 0.5f;
            break;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    // draw
    CGContextSetLineWidth(context, inset);
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithRGB:PCColorGrey].CGColor);
    CGContextMoveToPoint(context, 0, CGRectGetHeight(rect)-inset);
    CGContextAddLineToPoint(context, CGRectGetWidth(rect), CGRectGetHeight(rect)-inset);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);
}