我想知道绘制单点线的最佳方法是什么? 我的目标是在tableViewCell中绘制这一行,使其看起来就像本机单元格分隔符。 我不想使用原生分隔符,因为我想制作不同的颜色和不同的位置(不是底部..)。
起初我使用1px UIView并将其涂成灰色。但在Retina显示器中它看起来像2px。 也尝试使用这种方法:
- (void)drawLine:(CGPoint)startPoint endPoint:(CGPoint)endPoint inColor:(UIColor *)color {
CGMutablePathRef straightLinePath = CGPathCreateMutable();
CGPathMoveToPoint(straightLinePath, NULL, startPoint.x, startPoint.y);
CGPathAddLineToPoint(straightLinePath, NULL, endPoint.x, endPoint.y);
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = straightLinePath;
UIColor *fillColor = color;
shapeLayer.fillColor = fillColor.CGColor;
UIColor *strokeColor = color;
shapeLayer.strokeColor = strokeColor.CGColor;
shapeLayer.lineWidth = 0.5f;
shapeLayer.fillRule = kCAFillRuleNonZero;
[self.layer addSublayer:shapeLayer];
}
由于某种原因,它在60%的时间内起作用..它有什么问题吗? 无论如何,我很高兴听到更好的方式。
感谢。
答案 0 :(得分:17)
我对UIView
类别做了同样的事情。以下是我的方法:
#define SEPARATOR_HEIGHT 0.5
- (void)addSeparatorLinesWithColor:(UIColor *)color
{
[self addSeparatorLinesWithColor:color edgeInset:UIEdgeInsetsZero];
}
- (void)addSeparatorLinesWithColor:(UIColor *)color edgeInset:(UIEdgeInsets)edgeInset
{
UIView *topSeparatorView = [[UIView alloc] initWithFrame:CGRectMake(edgeInset.left, - SEPARATOR_HEIGHT, self.frame.size.width - edgeInset.left - edgeInset.right, SEPARATOR_HEIGHT)];
[topSeparatorView setBackgroundColor:color];
[self addSubview:topSeparatorView];
UIView *separatorView = [[UIView alloc] initWithFrame:CGRectMake(edgeInset.left, self.frame.size.height + SEPARATOR_HEIGHT, self.frame.size.width - edgeInset.left - edgeInset.right, SEPARATOR_HEIGHT)];
[separatorView setBackgroundColor:color];
[self addSubview:separatorView];
}
只是为了增加Rémy的好答案,这可能更简单。上课UILine.m
@interface UILine:UIView
@end
@implementation UILine
-(id)awakeFromNib
{
// careful, contentScaleFactor does NOT WORK in storyboard during initWithCoder.
// example, float sortaPixel = 1.0/self.contentScaleFactor ... does not work.
// instead, use mainScreen scale which works perfectly:
float sortaPixel = 1.0/[UIScreen mainScreen].scale;
UIView *topSeparatorView = [[UIView alloc] initWithFrame:
CGRectMake(0, 0, self.frame.size.width, sortaPixel)];
topSeparatorView.userInteractionEnabled = NO;
[topSeparatorView setBackgroundColor:self.backgroundColor];
[self addSubview:topSeparatorView];
self.backgroundColor = [UIColor clearColor];
self.userInteractionEnabled = NO;
}
@end
在IB中,放入UIView,单击身份检查器并将该类重命名为UILine。在IB中设置所需的宽度。将高度设置为1或2像素 - 这样您就可以在IB中看到它。在IB中设置所需的背景颜色。当您运行应用程序时,它将成为1像素线,即该颜色的宽度。 (你可能不应该受到storyboard / xib中任何默认自动调整大小设置的影响,我无法让它破裂。)你已经完成了。
注意:您可能会想“为什么不在awakeFromNib中的调整UIView 的大小?”在故事板应用程序中加载视图时加载视图是有问题的 - 请参阅此处的许多问题!
有趣的gotchya :你可能只是在故事板上制作UIView,比如10或20像素高,这样你就可以看到它。当然它在应用程序中消失了,你得到了漂亮的一个像素线。但!一定要记住self.userInteractionEnabled = NO
,否则它可能会超过你的其他按钮!
答案 1 :(得分:2)
shapeLayer.lineWidth = 0.5f;
这是一个常见的错误,也是这种情况仅在某些时候起作用的原因。有时这会完全重叠屏幕上的像素,有时它会赢。绘制始终有效的单点线的方法是在整数边界上绘制一个点厚的矩形,然后填充它。这样,它将始终完全匹配屏幕上的像素。
要从点转换为像素,如果您想这样做,请使用视图的比例因子。
因此,这将始终是一个像素宽:
CGContextFillRect(con, CGRectMake(0,0,desiredLength,1.0/self.contentScaleFactor));
这是一个屏幕截图,显示用作分隔符的行,绘制在每个单元格的顶部:
表视图本身没有分隔符(如三个现有单元格下方的空白区域所示)。我可能不会在你想要的位置,长度和颜色上划清界限,但那是你的关注,而不是我的。
答案 2 :(得分:2)
AutoLayout方法:
我使用普通的旧UIView并在Interface Builder中将其高度约束设置为1。通过约束将其附加到底部。界面构建器不允许您将高度约束设置为0.5,但您可以在代码中执行此操作。
为高度约束创建一个连接器,然后调用它:
// Note: This will be 0.5 on retina screens
self.dividerViewHeightConstraint.constant = 1.0/[UIScreen mainScreen].scale
为我工作。
FWIW我认为我们不再需要支持非视网膜屏幕了。但是,我仍然使用主屏幕比例来证明应用程序的未来。
答案 3 :(得分:1)
您必须考虑视网膜引起的缩放,并且您不是指屏幕像素。请参阅Core Graphics Points vs. Pixels。
答案 4 :(得分:0)
除了RémyVirin的回答,使用Swift 3.0 创建LineSeparator类:
import UIKit
class LineSeparator: UIView {
override func awakeFromNib() {
let sortaPixel: CGFloat = 1.0/UIScreen.main.scale
let topSeparatorView = UIView()
topSeparatorView.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: sortaPixel)
topSeparatorView.isUserInteractionEnabled = false
topSeparatorView.backgroundColor = self.backgroundColor
self.addSubview(topSeparatorView)
self.backgroundColor = UIColor.clear
self.isUserInteractionEnabled = false
}
}