与自动布局一起绘制分隔线
我UISplitViewController
某种UISplitViewController
。 现在我需要在主视图和详细视图之间绘制分隔线。 现在我有这个问题:
- 分隔线应该在视图控制器本身上,还是应该是一个单独的视图?
- 自动布局怎么样? 设置一个框架是不允许的。
我看到CALayer
/ CAShapeLayer
, drawRect
(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) } }
将@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
我实例DividerView
与DividerView 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。