索引处的 Swift 方法 insertSubview 效果很好。但是如何重新定位所有子视图为插入的子视图腾出空间

Posted

技术标签:

【中文标题】索引处的 Swift 方法 insertSubview 效果很好。但是如何重新定位所有子视图为插入的子视图腾出空间【英文标题】:Swift method insertSubview at index works well. But how to reposition all subviews to make room for inserted one 【发布时间】:2017-06-22 05:05:24 【问题描述】:

我以编程方式向特定视图添加了 4 个子视图(label1、label2、label3、label4)和约束(label2 顶部取决于 label1 底部等)。现在我使用 insertSubiewAtIndex 方法在索引 1(label5) 处插入另一个子视图。现在如何在约束是动态的情况下刷新 UI 意味着 label5 应该占据 label1 位置,而 label1 应该占据 label2 位置等等。

这是我的代码

override func viewDidLoad() 
    super.viewDidLoad()

    let label1 = UILabel()
    label1.translatesAutoresizingMaskIntoConstraints = false
    label1.text = "label1"
    label1.numberOfLines = 0
    label1.tag = 1

    self.containerView.addSubview(label1)

    NSLayoutConstraint(item: label1, attribute: .top, relatedBy: .equal, toItem: self.containerView, attribute: .top, multiplier: 1.0, constant: 16.0).isActive = true

    NSLayoutConstraint(item: label1, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true

    NSLayoutConstraint(item: label1, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true


    let label2 = UILabel()
    label2.translatesAutoresizingMaskIntoConstraints = false
    label2.text = "label2"
    label2.numberOfLines = 0
    label2.tag = 1

    self.containerView.addSubview(label2)

    NSLayoutConstraint(item: label2, attribute: .top, relatedBy: .equal, toItem: self.containerView.subviews[self.containerView.subviews.count - 2], attribute: .top, multiplier: 1.0, constant: 16.0).isActive = true

    NSLayoutConstraint(item: label2, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true

    NSLayoutConstraint(item: label2, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true


    let label3 = UILabel()
    label3.translatesAutoresizingMaskIntoConstraints = false
    label3.text = "label3"
    label3.numberOfLines = 0
    label3.tag = 1

    self.containerView.addSubview(label3)

    NSLayoutConstraint(item: label3, attribute: .top, relatedBy: .equal, toItem: self.containerView.subviews[self.containerView.subviews.count - 2], attribute: .top, multiplier: 1.0, constant: 16.0).isActive = true

    NSLayoutConstraint(item: label3, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true

    NSLayoutConstraint(item: label3, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true


    let label4 = UILabel()
    label4.translatesAutoresizingMaskIntoConstraints = false
    label4.text = "label4"
    label4.numberOfLines = 0
    label4.tag = 1

    self.containerView.addSubview(label4)

    NSLayoutConstraint(item: label4, attribute: .top, relatedBy: .equal, toItem: self.containerView.subviews[self.containerView.subviews.count - 2], attribute: .top, multiplier: 1.0, constant: 16.0).isActive = true

    NSLayoutConstraint(item: label4, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true

    NSLayoutConstraint(item: label4, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true

    let label5 = UILabel()
    label5.translatesAutoresizingMaskIntoConstraints = false
    label5.text = "label5"
    label5.numberOfLines = 0
    label5.tag = 1

    self.containerView.addSubview(label5)

    NSLayoutConstraint(item: label5, attribute: .top, relatedBy: .equal, toItem: self.containerView.subviews[0], attribute: .top, multiplier: 1.0, constant: 16.0).isActive = true

    NSLayoutConstraint(item: label5, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true

    NSLayoutConstraint(item: label5, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true


【问题讨论】:

【参考方案1】:
override func viewDidLoad() 
        super.viewDidLoad()

        containerView.backgroundColor = .white
        let label1 = UILabel()
        label1.translatesAutoresizingMaskIntoConstraints = false
        label1.text = "label1"
        label1.numberOfLines = 0
        label1.tag = 1

        self.containerView.addSubview(label1)

        let label2 = UILabel()
        label2.translatesAutoresizingMaskIntoConstraints = false
        label2.text = "label2"
        label2.numberOfLines = 0
        label2.tag = 1

        self.containerView.addSubview(label2)

        let label3 = UILabel()
        label3.translatesAutoresizingMaskIntoConstraints = false
        label3.text = "label3"
        label3.numberOfLines = 0
        label3.tag = 1

        self.containerView.addSubview(label3)

        let label4 = UILabel()
        label4.translatesAutoresizingMaskIntoConstraints = false
        label4.text = "label4"
        label4.numberOfLines = 0
        label4.tag = 1

        self.containerView.addSubview(label4)

        let label5 = UILabel()
        label5.translatesAutoresizingMaskIntoConstraints = false
        label5.text = "label5"
        label5.numberOfLines = 0
        label5.tag = 1

        self.containerView.addSubview(label5)

        setConstraint(to: [label5, label1, label2, label3, label4])
    

    private func setConstraint(to views: [UIView]) 
        var iterator  = views.makeIterator()
        var prev: UIView = self.containerView
        while let next = iterator.next() 
            NSLayoutConstraint(item: next, attribute: .top, relatedBy: .equal, toItem: prev, attribute: .top, multiplier: 1, constant: 16).isActive = true
            NSLayoutConstraint(item: next, attribute: .leading, relatedBy: .equal, toItem: self.containerView, attribute: .leadingMargin, multiplier: 1, constant: 0).isActive = true

            NSLayoutConstraint(item: next, attribute: .trailing, relatedBy: .equal, toItem: self.containerView, attribute: .trailingMargin, multiplier: 1, constant: 0).isActive = true
            prev = next
        
    

【讨论】:

我真正想要实现的是 - 我想在任何事件的父视图的特定索引处插入一个视图。父视图已经加载并且有许多带有约束的视图。可以说事件是在同一个父视图内切换。在点击开关时,我想在开关后在索引处插入一个视图,在关闭时添加的视图应该被删除。我的问题是所有约束都已经存在,并且有许多不同类型的视图。所有约束都是动态的,如 self.containerView.subviews[self.containerView.subviews.count - 2]。我是否必须删除约束并再次添加它们? 是的。 contentView.removeConstraints(contentView.constraints) 然后添加新的约束。

以上是关于索引处的 Swift 方法 insertSubview 效果很好。但是如何重新定位所有子视图为插入的子视图腾出空间的主要内容,如果未能解决你的问题,请参考以下文章

代码转换 swift 2 --> 3 导致索引路径处的二进制运算符错误

在索引处的 List<T> 中添加值的 C# 方法

不同部分的索引处的选择行

选择排序

索引 0 处的 InsertItem - DoubleLinkedList

替换字符串中特定索引处的字符?