与自动布局一起绘制分隔线

UISplitViewController某种UISplitViewController 。 现在我需要在主视图和详细视图之间绘制分隔线。 现在我有这个问题:

  • 分隔线应该在视图控制器本身上,还是应该是一个单独的视图?
  • 自动布局怎么样? 设置一个框架是不允许的。

我看到CALayer / CAShapeLayerdrawRect (CoreGraphics)或使用UIView / UILabel的背景颜色的解决scheme。 最后一个应该花费太多的performance在那里的人。

一方面,在UITableViewController本身画线是很舒服的。 或者应该创build一个单独的UIView ? 如果我embedded一个单独的UIView会有更多的约束,它会复杂的事情(将不得不设置单独的宽度)…也应适应方向的变化(例如UITableViewController的大小改变 – >分隔线也应调整)。

我怎样才能添加这样的分割规则? 这里可以看到这样的划分规则: 分隔线划分主控和细节视图控制器

如果你需要添加一个真正的一个像素线 ,不要愚弄一个图像。 这几乎是不可能的。 只需使用这个:

 @interface UILine : UIView @end @implementation UILine - (void)awakeFromNib { CGFloat sortaPixel = 1 / [UIScreen mainScreen].scale; // recall, the following... // CGFloat sortaPixel = 1 / self.contentScaleFactor; // ...does NOT work when loading from storyboard! UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, sortaPixel)]; line.userInteractionEnabled = NO; line.backgroundColor = self.backgroundColor; line.autoresizingMask = UIViewAutoresizingFlexibleWidth; [self addSubview:line]; self.backgroundColor = [UIColor clearColor]; self.userInteractionEnabled = NO; } @end 

如何使用:

实际上,在故事板中,只需制作一个位于确切位置的UIView ,并确定宽度即可 。 (随意使用限制/自动布局正常。)

让视图说五个像素高,只是让你可以清楚地看到它,而工作。

使UIView的顶部正好在你想要的单像素线的位置。 使UIView的行所需的颜色

将类更改为UILine在运行时 ,它将在所有设备的确切位置绘制一个完美的单像素线。

(对于垂直线类,只需修改CGRectMake。)

希望能帮助到你!

我把@ joe-blow的优秀答案更进一步,创造了一种不仅在IB中呈现的视图,而且还通过IB中的视察员来改变其线宽和线颜色。 简单地添加一个UIView到你的故事板,适当的尺寸,并将类更改为LineView

 import UIKit @IBDesignable class LineView: UIView { @IBInspectable var lineWidth: CGFloat = 1.0 @IBInspectable var lineColor: UIColor? { didSet { lineCGColor = lineColor?.CGColor } } var lineCGColor: CGColorRef? override func drawRect(rect: CGRect) { // Draw a line from the left to the right at the midpoint of the view's rect height. let midpoint = self.bounds.size.height / 2.0 let context = UIGraphicsGetCurrentContext() CGContextSetLineWidth(context, lineWidth) if let lineCGColor = self.lineCGColor { CGContextSetStrokeColorWithColor(context, lineCGColor) } else { CGContextSetStrokeColorWithColor(context, UIColor.blackColor().CGColor) } CGContextMoveToPoint(context, 0.0, midpoint) CGContextAddLineToPoint(context, self.bounds.size.width, midpoint) CGContextStrokePath(context) } } 

LineView的检查器

在故事情节中呈现的LineView

将@mharper答案更新到Swift 3.x

 import UIKit @IBDesignable class LineView: UIView { @IBInspectable var lineWidth: CGFloat = 1.0 @IBInspectable var lineColor: UIColor? { didSet { lineCGColor = lineColor?.cgColor } } var lineCGColor: CGColor? override func draw(_ rect: CGRect) { // Draw a line from the left to the right at the midpoint of the view's rect height. let midpoint = self.bounds.size.height / 2.0 if let context = UIGraphicsGetCurrentContext() { context.setLineWidth(lineWidth) if let lineCGColor = self.lineCGColor { context.setStrokeColor(lineCGColor) } else { context.setStrokeColor(UIColor.black.cgColor) } context.move(to: CGPoint(x: 0.0, y: midpoint)) context.addLine(to: CGPoint(x: self.bounds.size.width, y: midpoint)) context.strokePath() } } } 

新的代码

这应该适用于水平线和垂直线:

 /// <summary> /// Used as separator line between UIView elements with a given color. /// </summary> public class DividerView : UIView { private UIColor color; public DividerView () { this.color = UIColor.Black; } public DividerView (UIColor color) { this.color = color; } public override void Draw (CGRect rect) { base.Draw (rect); // get graphics context CGContext context = UIGraphics.GetCurrentContext (); // set up drawing attributes color.SetStroke (); color.SetFill (); // assumption: we can determine if the line is horizontal/vertical based on it's size nfloat lineWidth = 0; nfloat xStartPosition = 0; nfloat yStartPosition = 0; nfloat xEndPosition = 0; nfloat yEndPosition = 0; if (rect.Width > rect.Height) { // horizontal line lineWidth = rect.Height; xStartPosition = rect.X; // Move the path down by half of the line width so it doesn't straddle pixels. yStartPosition = rect.Y + lineWidth * 0.5f; xEndPosition = rect.X + rect.Width; yEndPosition = yStartPosition; } else { // vertical line lineWidth = rect.Width; // Move the path down by half of the line width so it doesn't straddle pixels. xStartPosition = rect.X + lineWidth * 0.5f; yStartPosition = rect.Y; xEndPosition = xStartPosition; yEndPosition = rect.Y + rect.Height; } // start point context.MoveTo (xStartPosition, yStartPosition); // end point context.AddLineToPoint (xEndPosition, yEndPosition); context.SetLineWidth (lineWidth); // draw the path context.DrawPath (CGPathDrawingMode.Stroke); } } 

原始答案

在自动布局项目中使用框架似乎不适合我。 另外,我会需要在自动布局应用后的实际框架,比我不得不在其上再绘制另一个视图。 基于帧的固定布局是没有问题的,但不在这里。 这就是为什么我现在select以下apporach:

我创build了UIView一个子类,并覆盖了UIView中Draw线的 drawRect ,或者如何从视图控制器以编程方式绘制一条线? 。 这是另一种select。

因为我使用的是C#,所以我给出了这种编程语言的代码示例。 在我发布的链接中,如果你愿意的话,你可以得到Objective-C的版本。

DividerView

 using System; using MonoTouch.Foundation; using MonoTouch.UIKit; using MonoTouch.CoreGraphics; using System.CodeDom.Compiler; using System.Drawing; namespace ContainerProject { public class DividerView : UIView { public DividerView () { } public override void Draw (RectangleF rect) { base.Draw (rect); // get graphics context CGContext context = UIGraphics.GetCurrentContext (); // set up drawing attributes UIColor.Black.SetStroke (); UIColor.Black.SetFill (); context.SetLineWidth (rect.Width); // start point context.MoveTo (rect.X, 0.0f); // end point context.AddLineToPoint (rect.X, rect.Y + rect.Height); // draw the path context.DrawPath (CGPathDrawingMode.Stroke); } } } 

在我的容器类的viewDidLoad我实例DividerViewDividerView separator = new DividerView ();

自动布局

然后我使用自动布局布局它的位置(全部在viewDidLoad ):

 separator.TranslatesAutoresizingMaskIntoConstraints = false; separatorTop = NSLayoutConstraint.Create (separator, NSLayoutAttribute.Top, NSLayoutRelation.Equal, TopLayoutGuide, NSLayoutAttribute.Bottom, 1, 0); separatorBottom = NSLayoutConstraint.Create (separator, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, BottomLayoutGuide, NSLayoutAttribute.Top, 1, 0); separatorRight = NSLayoutConstraint.Create (separator, NSLayoutAttribute.Right, NSLayoutRelation.Equal, documentListController.View, NSLayoutAttribute.Left, 1, 0); separatorWidth = NSLayoutConstraint.Create (separator, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 1); this.View.AddSubview (separator); 

这里添加了约束条件:

 public override void UpdateViewConstraints () { if (!hasLoadedConstraints) { this.View.AddConstraints (new NSLayoutConstraint[] { separatorTop, separatorBottom, separatorRight, separatorWidth }); hasLoadedConstraints = true; } base.UpdateViewConstraints (); } 

结果

这种方法似乎工作。 现在我的分隔线重叠我的详细信息视图(只有第一点)。 可以调整值或更改主控和详细视图的约束条件,以便在分隔符之间留有空间。

替代品

也可以添加一个子视图到每个UITableViewCell的内容视图。 例子可以在这里或这里find。