简体   繁体   English

Stackview 交换或更改视图顺序

[英]Stackview exchange or change order of views

Stackview containing array of textfield is embedded in scrollview.包含文本字段数组的 Stackview 嵌入在滚动视图中。 I want to change the order of the text fields on some actions.我想更改某些操作中文本字段的顺序。 The way to remove and add the textfield results in distorted view.删除和添加文本字段的方式会导致视图失真。 I also tested by removing from scrollview.我还通过从滚动视图中删除来进行测试。 Normal stackview too the exchange does not appear properly.正常的堆栈视图也没有正确显示交换。 I am using indexes to change :我正在使用索引来更改:


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

It is strange behaviour, but problem with the autolayout system, that should be updated before you can add localityTF back. 这是一个奇怪的行为,但自动布局系统的问题,应该更新,然后才能添加localityTF。 Also don't forget that removeArrangedSubview does not remove the view from subviews array: 另外请不要忘记removeArrangedSubview不会从子视图数组中删除视图:

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

[self.stackView insertArrangedSubview:_label1 atIndex:2];   
[self.stackView setNeedsLayout];

This is my solution in Swift 3 . 这是我在Swift 3中的解决方案。 It can also be used without defining the view in the stackview. 它也可以在不定义stackview中的视图的情况下使用。

Here I am changing the locations of the views of a Stackview with two views: 这里我用两个视图更改Stackview视图的位置:

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

    stackView.insertArrangedSubview(myView, at: 1)
    stackView.setNeedsLayout()
}

Try this bunch of code for replacing views in UIStackView , without refreshing any layouts. 尝试使用这一堆代码来替换UIStackView中的视图,而无需刷新任何布局。

if let objView = stackView.arrangedSubviews.first {
        objView.removeFromSuperview()
}
stackView.insertArrangedSubview(yourView, at: 0)

This solution perfectly works.这个解决方案非常有效。 Call it every time and it will change the first stack element view with the last and vice versa.每次调用它,它都会将第一个堆栈元素视图更改为最后一个,反之亦然。

  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()
  }

If you use horizontal axis:如果使用水平轴:

stackView.semanticContentAttribute = .forceRightToLeft

If you use vertical axis:如果使用垂直轴:

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()
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM