После борьбы с программными динамическими элементами пользовательского интерфейса в течение последних нескольких недель я решил попробовать 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 игнорируется.
При указанных выше условиях. Это выход
Если я теперь изменю высоту intrisiContentSize моего пользовательского UIClass на любую другую, это произойдет:
public var size = CGSize(width: UIView.noIntrinsicMetric, height: 10)
override open var intrinsicContentSize: CGSize {
return size
}
результат:
Пожалуйста, помогите мне понять, что происходит, а что нет
Окончательный экран должен выглядеть примерно так: