UIScrollView содержимое не выкладывается правильно - PullRequest
0 голосов
/ 10 января 2020

Я провел два дня, пытаясь заставить это работать, и не повезло. Я потратил много времени на исследования здесь и в Google, и хотя есть некоторая информация о добавлении UIImageViews в UIScrollViews, похоже, не так уж много о другом контенте, таком как UITextFields & UILabels.

Ссылаясь на код ниже, у меня есть несколько проблем:

  1. contentView в myScrollView: даже если contentView имеет backgroundColor, ограничения и т. Д. c, contentView, кажется, не отображается правильно, но добавленные к нему подпредставления отображаются (см. Прикрепленный скриншот).
  2. UITextFields, добавленный в contentView scrollView, не корректно размещается, несмотря на установленные ограничения. Как видно на скриншоте, текстовые поля, расположенные за пределами этих представлений с аналогичными ограничениями, ДОЛЖНЫ быть правильно размечены - например, оранжевое текстовое поле.
  3. Вертикальная прокрутка не работает, чтобы показать (в этом случае thirdTextField, т. Е. Текстовое поле чирка) не отображается и не может перейти к нему. Как ни странно, если я наберу текст внутри secondTextField, то есть в красном текстовом поле, оно увеличится в размере и будет продолжать расти, и в конечном итоге автоматически активирует горизонтальную прокрутку для UIScrollView. Кроме того, не понимайте это как встроенный в containerView, который имеет ограничения, которые просто кажутся проигнорированными.

Любая помощь будет принята с благодарностью и заранее извиняюсь за вопрос типа 101.

Все нижеизложенное делается программно, а не через рассказы.

import UIKit

class ViewController: UIViewController {

    lazy var myScrollView: UIScrollView = {
        let view =  UIScrollView(frame: .zero)
        view.backgroundColor = .lightGray
        return view
    }()

    lazy var contentView: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        return view
    }()

    var firstTextField = UITextField()
    var secondtextField = UITextField()
    var thirdTextField = UITextField()
    var fourthTextField = UITextField()

    var firstLabel = UILabel()
    var secondLabel = UILabel()

    var aButton = UIButton()

    var keyboardToolBar = UIToolbar()


    override func viewDidLoad() {
        super.viewDidLoad()

        // Add first label
        view.addSubview(firstLabel)
        firstLabel.backgroundColor = .yellow
        firstLabel.text = "Yellow Label"

        // Layout first label
        firstLabel.translatesAutoresizingMaskIntoConstraints = false
        firstLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        firstLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
        firstLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20).isActive = true

        // Add first textfield
        view.addSubview(firstTextField)
        firstTextField.backgroundColor = .orange
        firstTextField.placeholder = "Orange TextField"

        // Layout first text field
        firstTextField.translatesAutoresizingMaskIntoConstraints = false
        firstTextField.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
        firstTextField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
        firstTextField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20).isActive = true
        firstTextField.inputAccessoryView = keyboardToolBar

        // Add scrollView
        view.addSubview(myScrollView)

        // Layout scrollview
        myScrollView.translatesAutoresizingMaskIntoConstraints = false
        myScrollView.topAnchor.constraint(equalTo: firstTextField.bottomAnchor, constant: 20).isActive = true
        myScrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0).isActive = true
        myScrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20.0).isActive = true
        myScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -200.0).isActive = true

        // Add ContentView inside scrollview
        myScrollView.addSubview(contentView)

        // layout contentview
        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.topAnchor.constraint(equalTo: myScrollView.topAnchor, constant: 20.0).isActive = true
        contentView.leftAnchor.constraint(equalTo: myScrollView.leftAnchor, constant: 20.0).isActive = true
        contentView.rightAnchor.constraint(equalTo: myScrollView.rightAnchor, constant: -20.0).isActive = true
        contentView.bottomAnchor.constraint(equalTo: myScrollView.bottomAnchor, constant: -20.0).isActive = true

        // Add secondTextfield - inside contentview
        contentView.addSubview(secondtextField)
        secondtextField.backgroundColor = .red
        secondtextField.placeholder = "Red TextField"
        secondtextField.inputAccessoryView = keyboardToolBar

        // Layout secondtextField - inside contentview
        secondtextField.translatesAutoresizingMaskIntoConstraints = false
        secondtextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 100).isActive = true
        secondtextField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
        secondtextField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true

        // Add thirdtextfield - inside contentview
        contentView.addSubview(thirdTextField)
        thirdTextField.backgroundColor = .brown
        thirdTextField.placeholder = "Brown TextField"
        thirdTextField.inputAccessoryView = keyboardToolBar

        // Layout thirdtextField - inside contentview
        thirdTextField.translatesAutoresizingMaskIntoConstraints = false
            // Placed 500 below secondtextfield to use through vertical scrolling
        thirdTextField.topAnchor.constraint(equalTo: secondtextField.topAnchor, constant: 500).isActive = true
        thirdTextField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
        thirdTextField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true

        // elements outside of scrollview
        // add fourthtextField
        view.addSubview(fourthTextField)
        fourthTextField.backgroundColor = .systemTeal
        fourthTextField.placeholder = "Teal Textfield"
        fourthTextField.inputAccessoryView = keyboardToolBar

        // layout fourthtextField - over the top of the scrollview (for testing/modelling purposes)
        fourthTextField.translatesAutoresizingMaskIntoConstraints = false
        fourthTextField.topAnchor.constraint(equalTo: firstTextField.bottomAnchor, constant: 300).isActive = true
        fourthTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
        fourthTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true

        // Add second label
        view.addSubview(secondLabel)
        secondLabel.backgroundColor = .green
        secondLabel.text = "Green Label"

        // Layout of second label
        secondLabel.translatesAutoresizingMaskIntoConstraints = false
        secondLabel.topAnchor.constraint(equalTo: view.bottomAnchor, constant: -150).isActive = true
        secondLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
        secondLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true

        // Add button
        view.addSubview(aButton)
        aButton.backgroundColor = .systemBlue
        aButton.setTitle("A Button", for: .normal)

        // Layout button
        aButton.translatesAutoresizingMaskIntoConstraints = false
        aButton.topAnchor.constraint(equalTo: view.bottomAnchor, constant: -100).isActive = true
        aButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
        aButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true

        // Add Target to BUtton
        aButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)

    }

}

enter image description here

Ответы [ 2 ]

1 голос
/ 10 января 2020

Ответ Шуртугала частично верен - вам нужно bottomAnchor на thirdTextField, чтобы дать contentView некоторую высоту:

thirdTextField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true

См. Комментарии к этому ответу для дополнительного обсуждения.

Однако я добавляю этот ответ в качестве подсказки. Возможно, вам будет гораздо проще работать с ограничениями и автоматическим макетом, если логически сгруппировать ограничения, как показано в отредактированном коде ниже:

class ViewController: UIViewController {

    lazy var myScrollView: UIScrollView = {
        let view =  UIScrollView(frame: .zero)
        view.backgroundColor = .lightGray
        return view
    }()

    lazy var contentView: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        return view
    }()

    var firstTextField = UITextField()
    var secondtextField = UITextField()
    var thirdTextField = UITextField()
    var fourthTextField = UITextField()

    var firstLabel = UILabel()
    var secondLabel = UILabel()

    var aButton = UIButton()

    var keyboardToolBar = UIToolbar()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add first label
        view.addSubview(firstLabel)
        firstLabel.backgroundColor = .yellow
        firstLabel.text = "Yellow Label"

        // Add first textfield
        view.addSubview(firstTextField)
        firstTextField.backgroundColor = .orange
        firstTextField.placeholder = "Orange TextField"

        firstTextField.inputAccessoryView = keyboardToolBar

        // Add scrollView
        view.addSubview(myScrollView)

        // Add ContentView inside scrollview
        myScrollView.addSubview(contentView)

        // Add secondTextfield - inside contentview
        contentView.addSubview(secondtextField)
        secondtextField.backgroundColor = .red
        secondtextField.placeholder = "Red TextField"
        secondtextField.inputAccessoryView = keyboardToolBar

        // Add thirdtextfield - inside contentview
        contentView.addSubview(thirdTextField)
        thirdTextField.backgroundColor = .brown
        thirdTextField.placeholder = "Brown TextField"
        thirdTextField.inputAccessoryView = keyboardToolBar

        // elements outside of scrollview
        // add fourthtextField
        view.addSubview(fourthTextField)
        fourthTextField.backgroundColor = .systemTeal
        fourthTextField.placeholder = "Teal Textfield"
        fourthTextField.inputAccessoryView = keyboardToolBar

        // Add second label
        view.addSubview(secondLabel)
        secondLabel.backgroundColor = .green
        secondLabel.text = "Green Label"

        // Add button
        view.addSubview(aButton)
        aButton.backgroundColor = .systemBlue
        aButton.setTitle("A Button", for: .normal)

        [firstLabel, firstTextField, myScrollView, contentView, secondtextField, thirdTextField, fourthTextField, secondLabel, aButton].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
        }

        NSLayoutConstraint.activate([

            // firstLabel 100-pts from top, 20-pts on each side
            firstLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
            firstLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20),
            firstLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20),

            // firstTextField 150-pts from top, 20-pts on each side
            firstTextField.topAnchor.constraint(equalTo: view.topAnchor, constant: 150),
            firstTextField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20),
            firstTextField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20),

            // myScrollView 20-pts from bottom of firstTextField
            // 20-pts on each side
            // 200-pts from bottom of view
            myScrollView.topAnchor.constraint(equalTo: firstTextField.bottomAnchor, constant: 20),
            myScrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0),
            myScrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20.0),
            myScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -200.0),

            // contentView (subview of myScrollView) 20-pts on each side
            // this will automatically define the scrollView's .contentSize
            // however, it does NOT control the SIZE of contentView
            contentView.topAnchor.constraint(equalTo: myScrollView.topAnchor, constant: 20.0),
            contentView.leftAnchor.constraint(equalTo: myScrollView.leftAnchor, constant: 20.0),
            contentView.rightAnchor.constraint(equalTo: myScrollView.rightAnchor, constant: -20.0),
            contentView.bottomAnchor.constraint(equalTo: myScrollView.bottomAnchor, constant: -20.0),

            // secondtextField (subview of contenView) 100-pts from top, 20-pts on each side
            secondtextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 100),
            secondtextField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            secondtextField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),

            // secondtextField (subview of contenView) 500-pts from top of secondtextField (should probably be from bottom of secondTextField)
            // 20-pts on each side
            // (end up being placed 500 below secondtextfield to use through vertical scrolling)
            thirdTextField.topAnchor.constraint(equalTo: secondtextField.topAnchor, constant: 500),
            thirdTextField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            thirdTextField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),

            // constraints which define the SIZE of contentView...

            // if we want contentView to fit the width of myScrollView (with 20-pts "padding" on each side)
            contentView.widthAnchor.constraint(equalTo: myScrollView.widthAnchor, constant: -40),
            // thirdTextField bottom 20-pts from contentView bottom (this will define contentView's height)
            thirdTextField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20),

            // fourthTextField 300-pts from bottom of firstTextField, 10-pts on each side
            fourthTextField.topAnchor.constraint(equalTo: firstTextField.bottomAnchor, constant: 300),
            fourthTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
            fourthTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),

            // secondLabel 150-pts from bottom of view, 20-pts on each side
            secondLabel.topAnchor.constraint(equalTo: view.bottomAnchor, constant: -150),
            secondLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            secondLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

            // aButton 100-pts from bottom of view, 20-pts on each side
            aButton.topAnchor.constraint(equalTo: view.bottomAnchor, constant: -100),
            aButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
            aButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),

        ])

        // Add Target to BUtton
        aButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)

    }

    @objc func buttonTapped() -> Void {
        print("button tapped")
    }

}

Результат:

enter image description here

после прокрутки:

enter image description here

0 голосов
/ 10 января 2020

Вам нужно добавить:

contentView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 40.0).isActive = true
contentView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -40.0).isActive = true

Таким образом, contentView / scrollView будет знать, что прокрутка является вертикальной и:

thirdTextField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true

, потому что contentView должен иметь ограничения для всех высоты, чтобы сделать правильный макет. Теперь вы увидите синий contentView, для остальной части макета ... idk man, вам нужно проверить значения.

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