gpt4 book ai didi

swift - 为什么navigationBar隐藏collectionView?

转载 作者:行者123 更新时间:2023-11-30 10:43:39 27 4
gpt4 key购买 nike

使用 Swift-5.0.1、iOS-12.2,

我成功地放置了一个带有自定义高度为 150 像素的屏幕宽单元格的 UICollectionView。

但是,导航栏隐藏了第一个单元格。

我看到了不同的声明,其中指出 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(或其他)的高度属性来正确设置collectionView上的contentInset吗??

我意识到对于 iPhone XS,正确的插图大约是 112 像素。这些是如何实现的?

下图说明了collectionView第一个单元格的导航栏隐藏。

enter image description here

我的 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")
}
}

最佳答案

我终于找到了解决办法。

Mykod的大力帮助下,我能够使用在 collectionViewCell 中显示的 imageView 的 contentMode 及其 anchor 约束。

解决方案如下:

PhotoListCollectionViewCell内,您可以设置contentMode以及clipsToBounce:

var mainImageView: UIImageView = {
let imgV = UIImageView()
imgV.contentMode = .scaleAspectFill
imgV.clipsToBounds = true
return imgV
}()

非常重要的是,您需要将顶部、前导、尾随和底部约束设置为等于单元格的顶部、前导、尾随和底部约束:


func setConstraints() {
addSubview(mainImageView)
mainImageView.translatesAutoresizingMaskIntoConstraints = false
mainImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
mainImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
mainImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
mainImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}

通过上述更改,imageView 现在在 navBar 之后立即启动(并且不再位于其后面) - 即现在一切正确:)

您不再需要在 CollectionViewController 的 viewDidLoad() 内使用 collectionView.contentInset = ...contentModeclipsToBounds 和正确的锚定 使问题消失。

enter image description here

关于swift - 为什么navigationBar隐藏collectionView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56280933/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com