У меня есть полноэкранный режим CollectionView, который прокручивается вертикально сверху вниз. Это сделано для навигации по различным уровням, начиная с уровня 1 внизу. Теперь я также включил CardViewController и добавил его в основной ViewController, называемый «HomeViewController», так что в нижней части видна только его часть.
Я пытаюсь добиться следующего:
Я бы хотел, чтобы у пользователя была возможность прокручивать все уровни и с этим изменять содержимое, отображаемое в CardViewController. Поэтому каждый раз, когда он переходит на следующий уровень, контент обновляется (levelName, levelDescription, ...). И с этим видимая часть CardViewController должна уменьшаться или расширяться.
Я мог бы просто добавить простой View в HomeViewController и удалить CardViewController, но пользователь также может провести CardViewController вверх и увидеть некоторые подробные сведения о текущем уровне позже, после того, как я исправлю эту проблему прямо здесь.
Моя проблема прямо сейчас:
При попытке обновить все значения, показанные в CardViewController, при перемещении CollectionView. к следующей камере, я не могу больше ударить назад. Я также не знаю, является ли способ, которым я реализовал это правильный и лучший способ реализовать такой сценарий.
Чтобы увидеть, что пользователь перешел в другую ячейку, я использую другой cell.backgroundColors, который так или иначе перестал работать при написании этого сообщения ...
HomeViewController, который содержит CardViewController, на котором Тексты меток должны обновляться при перемещении в другую ячейку:
import UIKit
class HomeViewController: UIViewController {
private let worldsCollectionViewCellID = "WorldsCollectionViewCellID"
private let worldsCollectionView: UICollectionView = {
...
}()
// A TEST ARRAY
private let levelsArray: [LevelModel] = [LevelModel(id: "01", title: "Mystery Land", description: "A landscape full of mysterious animals and objects. Be aware of everything that is moving and try to escape their eyes. Otherwise your time has come very soon.", backgroundColor: UIColor.blue),
LevelModel(id: "02", title: "Land", description: "A landscape full of mysterious animals and objects. Be aware of everything that is moving and try to escape their eyes. Otherwise your time has come very soon. A landscape full of mysterious animals and objects. Be aware of everything that is moving and try to escape their eyes.", backgroundColor: UIColor.red)].reversed()
// CARD STUFF
enum CardState {
case expanded, collapsed
}
var cardViewController = CardViewController()
var totalCardHeight: CGFloat!
var visibleCardHeight: CGFloat!
var cardVisible = false
var nextState: CardState {
return cardVisible ? .collapsed : .expanded
}
var runningAnimations = [UIViewPropertyAnimator]()
var animationProgressWhenInterrupted: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
setupWorldsCollectionView()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// SCROLLING TO LAST ITEM
if (levelsArray.count > 0) {
let lastItemIndex = IndexPath(item: levelsArray.count - 1, section: 0)
worldsCollectionView.scrollToItem(at: lastItemIndex, at: .bottom, animated: false)
}
}
private func setupWorldsCollectionView() {
...
}
func setupCard(levelDescription: String) {
let calculatedCardViewControllerTextViewHeight = calculateTextViewHeight(text: levelDescription, font: UIFont.systemFont(ofSize: 15), textViewWidth: UIScreen.main.bounds.width - 32)
if #available(iOS 11.0, *) {
let window = UIApplication.shared.windows[0]
let bottomPadding = window.safeAreaInsets.bottom
self.visibleCardHeight = 16 + 26 + 12 + calculatedCardViewControllerTextViewHeight + 12 + 50 + 16 + bottomPadding
} else {
self.visibleCardHeight = 16 + 26 + 12 + calculatedCardViewControllerTextViewHeight + 12 + 50 + 16
}
self.totalCardHeight = UIScreen.main.bounds.height / 1.5
self.addChild(cardViewController)
self.view.addSubview(cardViewController.view)
cardViewController.view.frame = CGRect(x: 0, y: self.view.frame.height - visibleCardHeight, width: self.view.bounds.width, height: totalCardHeight)
cardViewController.view.clipsToBounds = true
cardViewController.view.layer.cornerRadius = 16
let tapGestureRecognizer = ...
let panGestureRecognizer = ...
cardViewController.view.addGestureRecognizer(tapGestureRecognizer)
cardViewController.view.addGestureRecognizer(panGestureRecognizer)
}
@objc
func handleCardTap(recognizer: UITapGestureRecognizer) {
...
}
@objc
func handleCardPan(recognizer: UIPanGestureRecognizer) {
...
}
func animateTransitionIfNeeded(state: CardState, duration: TimeInterval) {
...
}
func updateInteractiveTransition(fractionCompleted: CGFloat) {
...
}
func continueInteractiveTransition() {
...
}
}
extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return levelsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: worldsCollectionViewCellID, for: indexPath)
cell.backgroundColor = levelsArray[indexPath.row].backgroundColor
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.bounds.width, height: view.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets.zero
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
// IMPORTANT PART
if !self.children.isEmpty {
cardViewController.view.removeFromSuperview()
cardViewController.removeFromParent()
}
setupCard(levelDescription: levelsArray[indexPath.row].description)
cardViewController.levelModel = levelsArray[indexPath.row]
}
}
CardViewController:
import UIKit
class CardViewController: UIViewController {
private let levelNameLabel = UILabel()
private let levelDescriptionTextView = UITextView()
private let playButton = UIButton()
private var levelDescriptionTextViewHeightAnchor: NSLayoutConstraint!
// CALLED EVERY TIME THE MODEL CHANGES
var levelModel: LevelModel? {
didSet {
levelNameLabel.text = "Level \(levelModel?.id ?? "?"): \(levelModel?.title ?? "?")"
levelDescriptionTextView.text = levelModel?.description
changeLevelDescriptionTextViewHeightAnchor(levelDescription: levelModel?.description ?? "?")
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(named: "PrimaryBackgroundColor")
setupLevelNameLabel()
setupLevelDescriptionTextView()
setupPlayButton()
}
private func setupLevelNameLabel() {
...
}
private func setupLevelDescriptionTextView() {
...
// STANDARD ONE LINE SIZE
levelDescriptionTextViewHeightAnchor = levelDescriptionTextView.heightAnchor.constraint(equalToConstant: 19)
levelDescriptionTextViewHeightAnchor.isActive = true
}
private func setupPlayButton() {
...
}
private func changeLevelDescriptionTextViewHeightAnchor(levelDescription: String) {
let calculatedLevelDescriptionTextViewHeight = calculateTextViewHeight(text: levelDescription, font: UIFont.systemFont(ofSize: 15), textViewWidth: UIScreen.main.bounds.width - 32)
levelDescriptionTextViewHeightAnchor.isActive = false
levelDescriptionTextViewHeightAnchor = levelDescriptionTextView.heightAnchor.constraint(equalToConstant: calculatedLevelDescriptionTextViewHeight)
levelDescriptionTextViewHeightAnchor.isActive = true
}
}
И вот как это должно выглядеть в первой ячейке и другой ячейке (только примеры ):
Уровень 2: ![level 2](https://i.stack.imgur.com/BkLPX.png)
Уровень 1: ![level 1](https://i.stack.imgur.com/yoa8U.png)