【发布时间】:2019-05-23 18:20:26
【问题描述】:
使用 Swift-5.0.1、iOS-12.2,
我成功地放置了一个 UICollectionView,其中包含自定义高度为 150 像素的屏幕宽单元格。
但是,navigationBar 隐藏了第一个单元格。
我看到了不同的声明,声明必须将 contentInset 应用于 collectionView。
但是,我发现的所有帖子都没有明确说明必须用作偏移量的数量(特别是考虑到所有新的 iPhone 屏幕并考虑到导航栏可能很大或很小的事实)。
我试过了:
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)
但没有一个值真正匹配所需的插图!
我的问题:我可以依赖 navigationController(或其他)的 height-property 来正确设置 collectionView 上的 contentInset 吗??
我意识到对于 iPhone XS,正确的插图约为 112 像素。这些是如何实现的??
下图展示了 collectionView 的第一个单元格的 NavBar 隐藏。
我的 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")
}
}
【问题讨论】:
标签: swift uicollectionview uinavigationcontroller navbar viewcontroller