如何在iOS中绘制类似平行四边形的图形?

如何在iOS中绘制类似平行四边形的图形?,ios,drawing,polygon,uibezierpath,cashapelayer,Ios,Drawing,Polygon,Uibezierpath,Cashapelayer,我应该取得以下成果: 如您所见,它包含平行四边形(非矩形)列表,其中包含标签。而且,它可以是动态的,这意味着我可以使用stackview。首先,让我们绘制类似平行四边形的视图: class ParallelogramView: UIView { override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear } override func draw(_ rect: CGRec

我应该取得以下成果:

如您所见,它包含平行四边形(非矩形)列表,其中包含标签。而且,它可以是动态的,这意味着我可以使用stackview。首先,让我们绘制类似平行四边形的视图:

class ParallelogramView: UIView {

override init(frame: CGRect) {
    super.init(frame: frame)
    backgroundColor = .clear
}


override func draw(_ rect: CGRect) {
    super.draw(rect)
    let path = UIBezierPath()
    /// let's start from this point
    path.move(to: CGPoint(x: 8, y: 0))
    /// drawing horizontal top line till we can
    path.addLine(to: CGPoint(x: rect.maxX, y: 0))
    /// drawing to bottom but little bit to left
    path.addLine(to: CGPoint(x: rect.maxX - 16, y: rect.maxY))
    /// drawing from right to left
    path.addLine(to: CGPoint(x: 0, y: rect.maxY))
    /// connecting all
    path.close()
    
    /// just for sample filling it with some color. I don't know how to change it later :(
    UIColor.red.setFill()
    
    path.fill()
}
}
所有代码都有注释。然后,让我们定义一个
LabelView
,它包含一个带有标签的平行四边形

class LabelView: UIView {

/// out text
lazy var label: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

/// our parallelogramView
lazy var plView: ParallelogramView = {
    let trView = ParallelogramView()
    trView.translatesAutoresizingMaskIntoConstraints = false
    return trView
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    
    /// adding label to paralleogram
    plView.addSubview(label)
    addSubview(plView)
    
    NSLayoutConstraint.activate([
        plView.leadingAnchor.constraint(equalTo: leadingAnchor),
        plView.trailingAnchor.constraint(equalTo: trailingAnchor),
        plView.bottomAnchor.constraint(equalTo: bottomAnchor),
        plView.topAnchor.constraint(equalTo: topAnchor),
        
        label.leadingAnchor.constraint(equalTo: plView.leadingAnchor, constant: 16),
        label.trailingAnchor.constraint(equalTo: plView.trailingAnchor, constant: -16),
        label.bottomAnchor.constraint(equalTo: plView.bottomAnchor),
        label.topAnchor.constraint(equalTo: plView.topAnchor)
        
        
    ])
    
}
}

好的。我们的观点已经准备好了。现在,我们应该使用对齐填充将其添加到水平堆栈视图中

for item in ["Text", "Text", "Text"] {
        let labelView = LabelView()
        labelView.label.text = item
        stackView.addArrangedSubview(labelView)
    }
这是我们得到的结果


它不像期望的结果,因为它有理性的问题。据我所知,iOS中每个视图的框架都是矩形的,不能更改。即使我的stackview的间距是0,我仍然有一种间距(实际上没有),因为视图是矩形的。那么,如何实现屏幕截图这样的效果呢?我做错了什么?

这里有几个问题

首先,你画的平行四边形有点不稳定,左边的差是8倍,后面的差是16倍,所以它们不会对齐。您可以这样修复:

/// drawing to bottom but little bit to left
        path.addLine(to: CGPoint(x: rect.maxX - 8, y: rect.maxY))
第二,每个视图应该重叠,因为平行四边形当前完全在边界内。可以通过设置负间距在堆栈视图中执行此操作:

stackView.spating=-8

另一种方法是使平行四边形延伸到superview的边界之外,然后仍然可以使用原始尺寸作为其他布局的参考

不能使用
draw(urect:)
在视图边界之外进行绘制,因此不能仅以这种方式展开图形

要为平行四边形设置自定义颜色,请为其指定一个特性,然后在图形代码中使用该特性:

class ParallelogramView: UIView {

    //...

    var colour: UIColor = .red

    //...

    override func draw(_ rect: CGRect) {
        //... the rest of your drawing code
        colour.setFill()
        path.fill()
    }
}

labelView.plView.colour = .blue

好啊但如何动态地改变平行四边形的颜色呢?它是由
UIBezierPath
绘制的。那么如何在配置时访问它呢?还有最后一个问题。正如你们看到的,根据设计要求,平行四边形有点圆。我用圆角创建了
UIBezierPath
,比如
let path=UIBezierPath(roundedRect:rect,byRoundingCorners:[.bottomRight],cornerRadii:CGSize(宽度:8,高度:8))
,但现在它开始绘制的不是屏幕截图中的平行四边形,而是简单的矩形。问题是什么?这有点复杂,因为需要在路径上添加一个圆弧,并计算起点和终点角度。在这一点上,你最好使用一个可拉伸的图像作为背景,除非你有一个可变的高度以及为什么弧?添加曲线怎么样?