【问题标题】:AutoLayout divide width of view programaticallyAutoLayout 以编程方式划分视图的宽度
【发布时间】:2021-07-12 21:30:15
【问题描述】:

我一直在将一些代码从使用框架更改为使用自动布局,但遇到了一个小问题

对于我一直在构建日历的背景,我的问题在于我一直在尝试制作的日历的日视图,以便它复制苹果的日历。

这个应用程序自 2018 年以来一直放在我的硬盘中,所以有点过时了,但在 2018 年它做了以下事情:

通过创建EventContainerView 并将其放置在TableView 上(不是单元格)来显示Events

同时存在的事件会缩短它们的宽度以防止容器视图重叠。

这最后一部分是我的问题所在。

我通过获取 tableView 的宽度,将其除以重叠事件的数量,然后将其乘以 shiftBy 变量来将事件向右移动

在我的一生中,我看不到使用 autoLayout 实现这一点的方法。

在自动布局之前

func drawEvent(_ event:Event, overlaps:Int, shiftBy:Int) -> EventContainerView{
....
....


let eventWidth = (tableView.frame.width - 30) / CGFloat(overlaps)
        
        let shift = eventWidth * CGFloat(shiftBy)
        var frame: CGRect
     if(shiftBy > 0){
         frame = CGRect(x: CGFloat(30 + (5*shiftBy)) + shift, y: startPoint, width: eventWidth, height: endpoint)
         
     }else{
         frame = CGRect(x: CGFloat(30) + shift, y: startPoint, width: eventWidth, height: endpoint)
         
     }

自动布局后

func drawEvent(_ event:Event, overlaps:Int, shiftBy:Int) -> EventContainerView{
....
....

let eventView = EventContainerView(forEvent: event, today: self)
           eventView.translatesAutoresizingMaskIntoConstraints = false
 var left: NSLayoutConstraint = eventView.leftAnchor.constraint(equalTo: tableView.leftAnchor, constant: +20)
   
    if(shiftBy>0){
        left = ????
    }
    
    tableView.addSubview(eventView)
        let layout = [eventView.topAnchor.constraint(equalTo: tableView.topAnchor, constant: startPoint),
        left,
        eventView.heightAnchor.constraint(equalToConstant: endpoint),
        eventView.widthAnchor.constraint(equalTo: tableView.widthAnchor, multiplier: 1/CGFloat(overlaps), constant: -30)]
    NSLayoutConstraint.activate(layout)
        return eventView

任何人都可以就我如何实现这段代码提供任何建议吗?

谢谢

编辑

这就是我想要实现的(我在 macOS 的日历上使用了这个,但它仍然清楚地显示了我希望日历事件如何出现)

这就是我所拥有的(15 到 16 之间的深黄色是堆叠在“测试一切”事件下方的另一个事件。我需要其中一个切换(以及可能添加或可能不添加的任何其他事件)在同一时间范围内)

【问题讨论】:

  • 真的需要添加一些图片来展示你想要实现的目标。
  • @DonMag 我其实不知道我可以添加图片,我现在这样做是为了展示我想要的和我目前拥有的,谢谢

标签: ios swift autolayout


【解决方案1】:

许多不同的方法来解决这个问题,但要让它接近你正在做的事情......

您可以通过以下方式创建跨越宽度的等宽视图,使用它们之间的固定间距和每边的特定“填充”:

  • 将第一个视图的前导限制为父视图的前导 + 填充
  • 将每个连续视图的前导限制为前一个视图的尾随 + 间距
  • 将最后一个视图的尾随限制为超级视图的尾随 - 填充

然后,约束每个视图的宽度等于前一个视图的宽度。

这是一个简单的例子:

class AndyViewController: UIViewController {

    let numEvents = 1
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // a var to track the previously added view
        var prevView: UIView!
        
        var startPoint: CGFloat = 100
        
        // create a couple eventViews
        for i in 0..<numEvents {
            let thisView = eventView()
            view.addSubview(thisView)
            
            // set top constraint
            thisView.topAnchor.constraint(equalTo: view.topAnchor, constant: startPoint).isActive = true
            
            // let's pretend each view is 20-pts "later"
            startPoint += 20.0
            
            // for now, make them all 50-pts tall
            thisView.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
            
            // if it's the first view
            if i == 0 {
                // constrain its leading to view leading + 30
                thisView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30.0).isActive = true
            } else {
                // make sure prevView has been set
                guard let pv = prevView else {
                    fatalError("Did something wrong!!!")
                }
                // start this view at the right-end of the previous view + 5
                thisView.leadingAnchor.constraint(equalTo: prevView.trailingAnchor, constant: 5.0).isActive = true
                // make this view width equal to previous view width
                thisView.widthAnchor.constraint(equalTo: pv.widthAnchor).isActive = true
            }
            
            // if it's the last view
            if i == numEvents - 1 {
                // constrain its trailing to view trailing -30
                thisView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
            }
            
            // set prevView to thisView
            prevView = thisView
        }
        
    }

    func eventView() -> UIView {
        let v = UIView()
        v.backgroundColor = UIColor.yellow.withAlphaComponent(0.8)
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }
    
}

结果,使用 1、2、3 或 4 个“事件”:

您应该能够根据自己的需要进行调整。

【讨论】:

  • 我花了这么长时间才弄清楚如何在我的代码中实现这个哈哈....我必须编写一个函数来按时间对事件进行排序,然后才能使用你的答案哈哈....但是谢谢,如果没有你的建议,我永远不会走到这一步 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多