在 iOS 7 上的 UITableViewCell 之间绘制自定义分隔线
Posted
技术标签:
【中文标题】在 iOS 7 上的 UITableViewCell 之间绘制自定义分隔线【英文标题】:Draw custom separator line between UITableViewCell on iOS 7 【发布时间】:2014-11-12 10:19:03 【问题描述】:因为我在使用UITableViewCell
之间的默认分隔线时遇到了一些麻烦,我想使用我自己的。因此我使用自动布局。 C# 是我使用的语言。你当然可以在 Objective-C 中提供解决方案。
在我的自定义单元格的构造函数中,我添加了我的视图UIView
:
separator = new DividerView ();
ContentView.Superview.AddSubview (separator);
必须将其添加到超级视图中,否则它不会覆盖附件区域。在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:[separator(1)]|
将适用于 iOS 8,但不适用于 iOS 7。
【问题讨论】:
只需要在contentView中添加子视图即可。在 iOS 7 上,我认为 contentView 是不透明的。或者可能是子视图无法添加到单元格的视图中...... 但contentView
不会占用单元格的整个宽度。另一部分 (accessoryView
) 未涵盖。我尝试将我的线路也添加到accessoryView
,但应用程序随后崩溃。在 iOS 7 上,contentView
似乎没有父级。另一个想法是向 contentView 添加自定义图像(与指示器相同)并对触摸做出反应。另一个想法是将行添加到backgroundView
。
【参考方案1】:
据我所知,我想到了两种可能来解决这个问题:
不要使用默认的附件视图,而是根本不使用附件视图。而是通过创建辅助视图所需的图像来伪造辅助视图(视网膜显示的屏幕截图或使用自定义图像或drawing 本身)。如果您有假附件视图,可以将其添加到 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
仅包含带有几个字段的 Draw
方法。
【讨论】:
【参考方案2】:此代码适用于我(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);
@结束
【讨论】:
PCTableViewCellSeparatorView
看起来如何?因此,您要在 contentView
上添加一个单独的视图,并将其放置在高度为 1 的底部。你需要细胞的属性做什么?为什么需要-64.0f
?是否将分隔符放入accessoryView
区域?如果苹果改变尺寸怎么办?我必须尝试您的解决方案以测试它是否在所有情况下都有效。目前我有一个解决方案,但如果它“真的”有效,我必须尝试一下。否则,如果我有时间,我会研究您的解决方案。
@testing 自定义视图类 PCTableViewCellSeparatorView :带有自定义 drawRect 的 UIView。我需要单元格的属性来设置分隔符颜色。 -64.0f
- 此约束有助于在单元格外画线,上方 accessoryView
。可能它不是完美的解决方案,但我在 iPad 和 iPhone 上对其进行了测试——它现在可以工作了。
嗯,正如我所想。如果 PCTableViewCellSeparatorView 不太大,也许您可以在答案中包含它。感谢您提供另一种方法/解决方法。正如我所说,如果我有时间,我会研究你的解决方案。目前,我正在与其他 iOS 错误作斗争......
@testing 我做到了。我为 UIScreen 使用了一个类别,但它是 [UIScreen mainScreen].scale 的简单界面包装器
@testing 哦,今天我发现,我的实现自定义分隔符视图会制动单元格的自动布局计算。请继续关注,我会努力解决的。以上是关于在 iOS 7 上的 UITableViewCell 之间绘制自定义分隔线的主要内容,如果未能解决你的问题,请参考以下文章
UIScrollView 框架在 iOS 8 和 iOS 7 上的大小不同
iOS 7 上的 UIBarButtonSystemItemRefresh
如何在 iOS 7.1 中更改 TabBar 上的图像和标签颜色?
iOS 6 和 iOS 7 上的 UICollectionView 重新加载
在调用 willRotateToInterfaceOrientation 时,iOS 7 与 iOS 8 上的 mainScreen 边界大小不同