21

包含文本字段数组的 Stackview 嵌入在滚动视图中。我想更改某些操作的文本字段的顺序。删除和添加文本字段的方式会导致视图失真。我还通过从滚动视图中删除进行了测试。正常的 stackview 也没有正确显示交换。我正在使用索引进行更改:


stackView.removeArrangedSubview(localityTF) stackView.insertArrangedSubview(localityTF, at: 2)

4

5 回答 5

30

这是一种奇怪的行为,但自动布局系统存在问题,应该在添加 localityTF 之前对其进行更新。也不要忘记removeArrangedSubview不会从子视图数组中删除视图:

[self.stackView removeArrangedSubview:_label1];
[self.stackView setNeedsLayout];
[self.stackView layoutIfNeeded];

[self.stackView insertArrangedSubview:_label1 atIndex:2];   
[self.stackView setNeedsLayout];
于 2016-12-26T07:23:12.857 回答
7

这是我在Swift 3中的解决方案。它也可以在不定义stackview中的视图的情况下使用。

在这里,我使用两个视图更改 Stackview 视图的位置:

if let myView = stackView.subviews.first {
    stackView.removeArrangedSubview(myView)
    stackView.setNeedsLayout()
    stackView.layoutIfNeeded()

    stackView.insertArrangedSubview(myView, at: 1)
    stackView.setNeedsLayout()
}
于 2018-07-13T08:35:21.083 回答
4

尝试使用这组代码替换UIStackView中的视图,而无需刷新任何布局。

if let objView = stackView.arrangedSubviews.first {
        objView.removeFromSuperview()
}
stackView.insertArrangedSubview(yourView, at: 0)
于 2019-04-10T05:14:17.293 回答
0

如果使用水平轴:

stackView.semanticContentAttribute = .forceRightToLeft

如果使用垂直轴:

import UIKit

enum VerticalSemanticContentAttribute {
    case forceTopToBottom, forceBottomToTop
}

final class VerticalStackView: UIStackView {
     var verticalSemanticContentAttribute:  VerticalSemanticContentAttribute = .forceTopToBottom {
        didSet {
             guard oldValue != verticalSemanticContentAttribute else { return }
        
             reverseArrangedSubviews()
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    
        axis = .vertical
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
    
        axis = .vertical
    }
}

// MARK: - Private functions
private extension VerticalStackView {
    func reverseArrangedSubviews() {
        let totalCount = arrangedSubviews.count
    
        for (index, view) in arrangedSubviews.enumerated().reversed() where index != 0 { // we don't need to reposition the last item. It's already in the right position
            removeArrangedSubview(view)
            view.removeFromSuperview()
            setNeedsLayout()
            layoutIfNeeded()
        
            let insertIndex = totalCount - index - 1
            insertArrangedSubview(view, at: insertIndex)
            setNeedsLayout()
            layoutIfNeeded()
        }
    }
}
于 2021-12-08T12:06:10.223 回答
0

该解决方案非常有效。每次调用它,它都会将第一个堆栈元素视图更改为最后一个,反之亦然。

  if let first = stackView.subviews.first, let last = stackView.subviews.last {
    stackView.subviews.forEach { $0.removeFromSuperview() }
    stackView.insertArrangedSubview(last, at: 0)
    stackView.insertArrangedSubview(first, at: 1)
    stackView.setNeedsLayout()
    stackView.layoutIfNeeded()
  }
于 2021-11-04T20:39:26.593 回答