Stretchy Layout не работает с дочерним контроллером вида - PullRequest
0 голосов
/ 18 февраля 2019

Я пытаюсь следовать описанному здесь примеру для создания растягивающейся компоновки, включающей UIImageView и UIScrollView.https://github.com/TwoLivesLeft/StretchyLayout/tree/Step-6

Единственное отличие состоит в том, что я заменяю UILabel, использованный в примере, на представление потомка UIViewController, которое само содержит UICollectionView.Вот так выглядит мой макет - синие элементы: UICollectionViewCell. enter image description here

Это мой код:

import UIKit
import SnapKit

class HomeController: UIViewController, UIScrollViewDelegate {

private let scrollView = UIScrollView()
private let imageView = UIImageView()
private let contentContainer = UIView()
private let collectionViewController = CollectionViewController()

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

override func viewDidLoad() {
    super.viewDidLoad()


    scrollView.contentInsetAdjustmentBehavior = .never
    scrollView.delegate = self

    imageView.image = UIImage(named: "burger")
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true

    let imageContainer = UIView()
    imageContainer.backgroundColor = .darkGray

    contentContainer.backgroundColor = .clear

    let textBacking = UIView()
    textBacking.backgroundColor = #colorLiteral(red: 0.7450980544, green: 0.1235740449, blue: 0.2699040081, alpha: 1)

    view.addSubview(scrollView)

    scrollView.addSubview(imageContainer)
    scrollView.addSubview(textBacking)
    scrollView.addSubview(contentContainer)
    scrollView.addSubview(imageView)

    self.addChild(collectionViewController)
    contentContainer.addSubview(collectionViewController.view)
    collectionViewController.didMove(toParent: self)


    scrollView.snp.makeConstraints {
        make in

        make.edges.equalTo(view)
    }

    imageContainer.snp.makeConstraints {
        make in

        make.top.equalTo(scrollView)
        make.left.right.equalTo(view)
        make.height.equalTo(imageContainer.snp.width).multipliedBy(0.7)
    }

    imageView.snp.makeConstraints {
        make in

        make.left.right.equalTo(imageContainer)

        //** Note the priorities
        make.top.equalTo(view).priority(.high)

        //** We add a height constraint too
        make.height.greaterThanOrEqualTo(imageContainer.snp.height).priority(.required)

        //** And keep the bottom constraint
        make.bottom.equalTo(imageContainer.snp.bottom)
    }

    contentContainer.snp.makeConstraints {
        make in

        make.top.equalTo(imageContainer.snp.bottom)
        make.left.right.equalTo(view)
        make.bottom.equalTo(scrollView)
    }

    textBacking.snp.makeConstraints {
        make in

        make.left.right.equalTo(view)
        make.top.equalTo(contentContainer)
        make.bottom.equalTo(view)
    }

    collectionViewController.view.snp.makeConstraints {
        make in

        make.left.right.equalTo(view)
        make.top.equalTo(contentContainer)
        make.bottom.equalTo(view)
    }

}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.scrollIndicatorInsets = view.safeAreaInsets
    scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: view.safeAreaInsets.bottom, right: 0)
}

//MARK: - Scroll View Delegate

private var previousStatusBarHidden = false

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if previousStatusBarHidden != shouldHideStatusBar {

        UIView.animate(withDuration: 0.2, animations: {
            self.setNeedsStatusBarAppearanceUpdate()
        })

        previousStatusBarHidden = shouldHideStatusBar
    }
}

//MARK: - Status Bar Appearance

override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
    return .slide
}

override var prefersStatusBarHidden: Bool {
    return shouldHideStatusBar
}

private var shouldHideStatusBar: Bool {
    let frame = contentContainer.convert(contentContainer.bounds, to: nil)
    return frame.minY < view.safeAreaInsets.top
}

}

Все так же, какв этом файле: https://github.com/TwoLivesLeft/StretchyLayout/blob/Step-6/StretchyLayouts/StretchyViewController.swift за исключением замены innerText на мой CollectionViewController.

Как видите, UICollectionView отображается правильно - однако я больше не могу прокручивать вверх или вниз.Я не уверен, где моя ошибка.

1 Ответ

0 голосов
/ 18 февраля 2019

Похоже, что вы ограничиваете размер представления коллекции, чтобы он соответствовал границам родительского представления, содержащего представление контейнера представления коллекции и представление изображения.В результате контейнер scrollView не имеет contentSize для прокрутки, и поэтому вы не можете прокручивать.Необходимо убедиться, что размер содержимого представления коллекции отражен в размере содержимого родительского представления прокрутки.

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

Редактировать: Точнее, вам нужно передать значение collectionView.contentSize до значения scrollView.contentSize.contentSize в scrollview можно установить, поэтому вам просто нужно увеличить scrollView.contentSize на collectionView.contentSize - collectionView.height (поскольку текущий contentSize вашего scrollView в настоящее время включает в себя высоту collectionView).Я не уверен, как вы добавляете свой дочерний контроллер представления, но в тот момент, когда вы это сделаете, я бы соответственно увеличил contentSize вашего scrollView.Если после этого размер вашего collectionView изменится, вам также необходимо убедиться, что вы делегировали это изменение до значения scrollView.Этого можно достичь, если иметь протокол, такой как:

protocol InnerCollectionViewHeightUpdated {
  func collectionViewContentHeightChanged(newSize: CGSize)
}

, а затем заставить контроллер, содержащий scrollView, реализовать этот протокол и соответственно обновить scrollView contentSize.В вашем дочернем контроллере collectionView у вас будет свойство delegate для этого протокола (установите его при создании дочернего контроллера представления, задав для делегата значение self, контроллер, содержащий дочерний VC, а также scrollView),Затем всякий раз, когда высота collectionView изменяется (например, если вы добавляете ячейки), вы можете выполнить delegate.collectionViewContentHeightChanged(..., чтобы гарантировать, что ваше поведение прокрутки продолжит функционировать.

...