StackView: переопределение пользовательского размера intrinsicContent UIview приводит к очень неожиданным результатам - PullRequest
0 голосов
/ 15 января 2019

После борьбы с программными динамическими элементами пользовательского интерфейса в течение последних нескольких недель я решил попробовать UIstackView. Я хочу, чтобы пользовательские классы UIView занимали вид в стеке с разной высотой в зависимости от пользовательского ввода, который я бы удалил, добавив представления на лету.

Я обнаружил, что stackViews основывают свою высоту «ячейки» на внутреннем размере контента элемента UI. Тем не менее, UIViews не имеют. Я искал повсюду и обнаружил, что мне нужно переопределить функцию intrisicContentsize в представлении, где я могу явно установить ширину и высоту. Однако результаты очень непредсказуемы, и я уверен, что есть кое-что, о чем я просто не знаю, что это странное поведение. Так как я новичок в этом языке и у меня немало проблем, я просто вставлю сюда код и надеюсь, что вы сможете определить, что я делаю неправильно.

Я прочитал документы ofc, много статей, все они указывают на эту функцию переопределения, которая, кажется, не работает со мной.

Это мой класс mainViewController;

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {

var bv = BackButtonView(frame: CGRect.zero, image: UIImage(named: "backArrow.png")!)

var redView : UIView  = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .red
    return view
}();

var blueView : UIView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .blue
    return view
}();

let stack : UIStackView = {
    let stack = UIStackView();
    stack.translatesAutoresizingMaskIntoConstraints = false;
    stack.axis = .vertical
    stack.distribution = .fillProportionally;
    stack.spacing = 8
    return stack;
}();

override func viewDidLoad() {
    let view = UIView(frame: UIScreen.main.bounds)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .white
    self.view = view
    self.view.addSubview(stack)
    createLayout()
    bv.intrinsicContentSize
    stack.addArrangedSubview(bv)
    print(bv.frame)
    print(bv.intrinsicContentSize)
    stack.layoutIfNeeded()
    stack.addArrangedSubview(redView)
    stack.addArrangedSubview(blueView)

}

private func setConstraints(view: UIView) -> [NSLayoutConstraint] {
    return [
        view.heightAnchor.constraint(equalToConstant: 50),
    ]
}

private func createLayout() {
    stack.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
    stack.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
    stack.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
    stack.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true

}
}

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = MyViewController()

Теперь вот мой пользовательский UIClass, который доставляет мне все эти неприятности:

import UIKit

public class BackButtonView : UIView {


public var size = CGSize(width: 10, height: UIView.noIntrinsicMetric)
override open var intrinsicContentSize: CGSize {
     return size
}

var button : UIButton;

public init(frame: CGRect, image: UIImage) {
    button = UIButton()
    super.init(frame : frame);
    self.translatesAutoresizingMaskIntoConstraints = false;
    self.backgroundColor = .black
    self.addSubview(button)
    setupButton(image: image);
    print(button.intrinsicContentSize)
}
let backButtonTrailingPadding : CGFloat = -18

lazy var buttonConstraints = [
    button.heightAnchor.constraint(equalToConstant: 50),
    button.widthAnchor.constraint(equalToConstant: 50),
    button.centerYAnchor.constraint(equalTo: self.centerYAnchor),
    button.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: backButtonTrailingPadding),
]
private func setupButton(image: UIImage) {
    self.button.translatesAutoresizingMaskIntoConstraints = false;
    self.button.setImage(image, for: .normal);
    self.button.contentMode = .scaleToFill
    NSLayoutConstraint.activate(buttonConstraints)

}
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

struct anchors {
    var topAnchor = NSLayoutConstraint()
    var bottomAnchor = NSLayoutConstraint()
    var leadingAnchor = NSLayoutConstraint()
    var trailingAnchor = NSLayoutConstraint()
}

}

Вы можете видеть, что указанная ширина в размере proprrty игнорируется. При указанных выше условиях. Это выход

Al heights are equal here Если я теперь изменю высоту intrisiContentSize моего пользовательского UIClass на любую другую, это произойдет:

    public var size = CGSize(width: UIView.noIntrinsicMetric, height: 10)
override open var intrinsicContentSize: CGSize {
     return size
}

результат: enter image description here

Пожалуйста, помогите мне понять, что происходит, а что нет

Окончательный экран должен выглядеть примерно так:

enter image description here

...