Сдерживание ViewController с подклассами - PullRequest
0 голосов
/ 28 марта 2020

в попытке подняться до уровня "избавления от массивных контроллеров представления" Я пытаюсь кое-что с использованием контроллера представления.

Вот что я хочу:

  • есть база класс с представлением прокрутки и встроенным представлением стека
  • наследуется от этого класса с помощью реализации моей желаемой сцены
  • , позволяющей добавлять контроллеры дочернего представления по мере необходимости в мою реализацию

Я ожидаю что-то вроде этого:

enter image description here

Вот код, с которым я пытаюсь добиться этого:

import UIKit

/**
Base class
*/
class PrototypeStackViewController: UIViewController {

    private let scrollView: UIScrollView = {
        let s = UIScrollView()
        s.translatesAutoresizingMaskIntoConstraints = false
        s.contentMode = .scaleToFill
        return s
    }()

    private let stackView: UIStackView = {
        let s = UIStackView()
        s.translatesAutoresizingMaskIntoConstraints = false
        s.axis = .vertical
        s.alignment = .fill
        s.distribution = .fill
        s.contentMode = .scaleToFill
        return s
    }()

    override func loadView() {
        view = UIView()
        view.backgroundColor = .systemGray

        view.addSubview(scrollView)
        scrollView.addSubview(stackView)

        let  nstraint = stackView.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor)
        stackViewHeightConstraint.priority = .defaultLow

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

            stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),

            stackViewHeightConstraint
        ])
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func add(child: UIViewController) {
        addChild(child)
        stackView.addArrangedSubview(child.view)
        child.didMove(toParent: self)
    }

    func remove(child: UIViewController) {
        guard child.parent != nil else { return }

        child.willMove(toParent: nil)
        stackView.removeArrangedSubview(child.view)
        child.view.removeFromSuperview()
        child.removeFromParent()
    }
}

/**
Implementation of my scene
*/
class PrototypeContainmentViewController: PrototypeStackViewController {

    lazy var topViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemRed
        t.label.text = "Top View Controller"
        return t
    }()

    lazy var centerViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemGreen
        t.label.text = "Center View Controller"
        return t
    }()

    lazy var bottomViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemBlue
        t.label.text = "Bottom View Controller"
        return t
    }()

    override func loadView() {
        super.loadView()

        add(child: topViewController)
        add(child: centerViewController)
        add(child: bottomViewController)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}

/**
Sample View Controller
*/
class PrototypeSubViewController: UIViewController {

    lazy var label: UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        return l
    }()

    override func loadView() {
        view = UIView()
        view.backgroundColor = .systemRed

        view.addSubview(label)

        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
            label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        ])
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Вот что я получаю:

enter image description here

Если вы посмотрите поближе, вы даже увидите ярлык «Контроллер нижнего обзора» - но сверху зеленый центр view controller.

Мне не хватает чего-то здесь в моем отношении любви-ненависти к автоматическому макету, это наверняка ...

Ответы [ 2 ]

1 голос
/ 28 марта 2020

Вам не хватает ограничения ширины, которое гарантирует, что представление стека заполняет ширину представления прокрутки:

stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)

Также я бы установил ваши ограничения меток следующим образом:

NSLayoutConstraint.activate([
    label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
    label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
    label.top.constraint(equalTo: view.topAnchor),
    label.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
0 голосов
/ 28 марта 2020

Нужно было сделать некоторые настройки, чтобы это работало.

Прежде всего, чтобы охватить всю ширину, мне не хватало stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor), что Франческо Делиро правильно сказал мне в другом ответе.

Кроме того, оказалось, что мне нужно было изменить свой дистрибутив stackViews на .fillProportionally.

Код, который мне удалось получить, который я показал на картинке вопроса, теперь таков:

/**
 Base Class
 */
class PrototypeStackViewController: UIViewController {

    private let scrollView: UIScrollView = {
        let s = UIScrollView()
        s.translatesAutoresizingMaskIntoConstraints = false
        s.contentMode = .scaleToFill
        return s
    }()

    private let stackView: UIStackView = {
        let s = UIStackView()
        s.translatesAutoresizingMaskIntoConstraints = false
        s.axis = .vertical
        s.alignment = .fill
        s.distribution = .fillProportionally //CHANGED to this
        s.contentMode = .scaleToFill
        return s
    }()

    override func loadView() {
        view = UIView()
        view.backgroundColor = .systemGray

        view.addSubview(scrollView)
        scrollView.addSubview(stackView)

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),

            //CHANGED set of constraints here, seems as though width and heigt anchors are needed
            stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            stackView.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
            stackView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
            stackView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor)
        ])
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func add(child: UIViewController) {
        addChild(child)
        stackView.addArrangedSubview(child.view)
        child.didMove(toParent: self)
    }

    func remove(child: UIViewController) {
        guard child.parent != nil else { return }

        child.willMove(toParent: nil)
        stackView.removeArrangedSubview(child.view)
        child.view.removeFromSuperview()
        child.removeFromParent()
    }
}

class PrototypeContainmentViewController: PrototypeStackViewController {

    lazy var topViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemRed
        t.label.text = "Top View Controller"
        return t
    }()

    lazy var centerViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemGreen
        t.label.text = "Center View Controller"
        return t
    }()

    lazy var bottomViewController: PrototypeSubViewController = {
        let t = PrototypeSubViewController()
        t.view.backgroundColor = .systemBlue
        t.label.text = "Bottom View Controller"
        return t
    }()

    override func loadView() {
        super.loadView()

        add(child: topViewController)
        add(child: centerViewController)
        add(child: bottomViewController)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

class PrototypeSubViewController: UIViewController {

    lazy var label: UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        l.textAlignment = .center
        return l
    }()

    override func loadView() {
        view = UIView()
        view.backgroundColor = .systemRed

        view.addSubview(label)

        NSLayoutConstraint.activate([
            //CHANGED to this set of constraints
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        ])
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Надеюсь, что этот ответ поможет будущему мне и, возможно, другим людям: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...