Используя Swift-5.0.1, iOS-12.2,
Мне удалось разместить UICollectionView с ячейками на весь экран с пользовательской высотой 150 пикселей.
ОднакоnavigationBar скрывает первую ячейку.
Я видел различные утверждения, в которых говорится, что contentInset должен быть применен к collectionView.
Однако ни в одной из найденных публикаций четко не указано количество, которое должнов качестве смещения (особенно учитывая все новые iPhone-экраны и учитывая тот факт, что navBar может быть большим или маленьким).
Я пытался:
let offset1 = self.navigationController?.navigationBar.frame.size.height
let offset2 = navigationController?.navigationBar.frame.maxY
self.edgesForExtendedLayout = []
self.collectionView.contentInset = UIEdgeInsets(top: offset2, left: 0, bottom: 0, right: 0)
Но ни один иззначения действительно совпадают с необходимой вставкой!
Мой вопрос: есть ли свойство height навигационного контроллера (или другого), на которое я могу положиться, чтобы правильно установить contentInset на collectionView ??
Я понял, что для iPhone XS правильная вставка составляет примерно 112 пикселей.Как это происходит ??
Следующие изображения иллюстрируют скрытие NavBar первой ячейки collectionView.
Мой NavigationController и UICollectionViewController создаются внутри AppDelegate.swift
следующим образом:
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
let vc = CollectionViewController()
let nc = UINavigationController(rootViewController: vc)
window?.rootViewController = nc
window?.makeKeyAndVisible()
return true
}
Здесь CollectionViewController:
import UIKit
class CollectionViewController: BaseListController, UICollectionViewDelegateFlowLayout {
fileprivate let cellId = "cellId"
fileprivate let activityIndicator = UIActivityIndicatorView()
lazy var viewModel: PhotoListViewModel = {
return PhotoListViewModel()
}()
override func viewDidLoad() {
super.viewDidLoad()
// Init the static view
initView()
// init view model
initVM()
}
func initView() {
self.navigationItem.title = "NavBar"
collectionView.register(PhotoListCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
collectionView.backgroundColor = .white
// a number of 112 makes the correct inset but why ???????
collectionView.contentInset = UIEdgeInsets(top: 112, left: 0, bottom: 0, right: 0)
}
func initVM() {
// Naive binding
viewModel.showAlertClosure = { [weak self] () in
DispatchQueue.main.async {
if let message = self?.viewModel.alertMessage {
self?.showAlert( message )
}
}
}
viewModel.updateLoadingStatus = { [weak self] () in
DispatchQueue.main.async {
let isLoading = self?.viewModel.isLoading ?? false
if isLoading {
self?.activityIndicator.startAnimating()
UIView.animate(withDuration: 0.2, animations: {
self?.collectionView.alpha = 0.0
})
}else {
self?.activityIndicator.stopAnimating()
UIView.animate(withDuration: 0.2, animations: {
self?.collectionView.alpha = 1.0
})
}
}
}
viewModel.reloadTableViewClosure = { [weak self] () in
DispatchQueue.main.async {
self?.collectionView.reloadData()
}
}
viewModel.initFetch()
}
func showAlert( _ message: String ) {
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
alert.addAction( UIAlertAction(title: "Ok", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.numberOfCells
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? PhotoListCollectionViewCell else {
fatalError("Cell not exists in storyboard")
}
let cellVM = viewModel.getCellViewModel( at: indexPath )
cell.photoListCellViewModel = cellVM
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: view.frame.width, height: 150)
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.viewModel.userPressed(at: indexPath)
if viewModel.isAllowSegue {
let detailVC = PhotoDetailViewController()
if let photo = viewModel.selectedPhoto {
detailVC.imageView = UIImageView()
detailVC.imageView.contentMode = .scaleAspectFill
detailVC.imageView.sd_setImage(with: URL(string: photo.image_url)) { (image, error, type, url) in
}
}
self.navigationController?.pushViewController(detailVC, animated: true)
}
}
}
С помощью BaseController ...
import UIKit
class BaseListController: UICollectionViewController {
init() {
super.init(collectionViewLayout: UICollectionViewFlowLayout())
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}