问题描述
我想以编程方式在导航栏、标签和底部的 tabBar 之间放置一个 collectionView.
I want to place a collectionView programmatically between a navigationBar, a label and the tabBar on the bottom.
我不想在不同部分之间有任何间距,如何正确地将视图添加到视图中?最好的方法是什么?
I do not want to have any spacing between the different parts, how do I correctly ad the views to the view? Whats the best way to do it?
import UIKit
private let reUseIdentifierCollectionView = "CollectionViewCell1"
class CVControllerViewController: UIViewController {
var heightNavigationBarTop: CGFloat{
get{
let barHeight = self.navigationController?.navigationBar.frame.height ?? 0
let statusBarHeight = UIApplication.shared.isStatusBarHidden ? CGFloat(0) : UIApplication.shared.statusBarFrame.height
return barHeight + statusBarHeight
}
}
//Here I am getting the SafeArea above the NavigationBar
var topSafeArea: CGFloat{
get{
var topSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = view.safeAreaInsets.top
} else {
topSafeArea = topLayoutGuide.length
}
return topSafeArea
}
}
var tabBarHeight: CGFloat{ get{ return (self.tabBarController?.tabBar.frame.height)! } }
lazy var label: UILabel = {
let lb = UILabel()
lb.frame = CGRect(x: 0, y: heightNavigationBarTop + topSafeArea, width: view.frame.width, height: 50)
lb.backgroundColor = .red
return lb
}()
var collectionView: UICollectionView!
var content = [Int: Any]()
override func viewDidLoad() {
super.viewDidLoad()
loadContent()
loadCollectionView()
view.addSubview(label)
view.addSubview(collectionView)
}
func loadCollectionView() {
let layout = UICollectionViewFlowLayout()
let frame = CGRect(x: 0, y: heightNavigationBarTop + label.frame.height + topSafeArea, width: self.view.frame.height, height: self.view.frame.height - (heightNavigationBarTop + label.frame.height + tabBarHeight + topSafeArea))
collectionView = UICollectionView(frame: frame, collectionViewLayout: layout)
collectionView.backgroundColor = .white
collectionView.register(CoinCVCCell.self, forCellWithReuseIdentifier: reUseIdentifierCollectionView)
if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.scrollDirection = .horizontal
flowLayout.minimumLineSpacing = 0
}
collectionView.delegate = self
collectionView.dataSource = self
}
func loadContent() {
content[0] = Content(name: "Blau", color: .blue)
content[1] = Content(name: "Grün", color: .green)
content[2] = Content(name: "Gelb", color: .yellow)
content[3] = Content(name: "brown", color: .brown)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension CVControllerViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let outputCell: UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseIdentifierCollectionView, for: indexPath) as! CoinCVCCell
cell.content = (content[indexPath.item] as! Content)
outputCell = cell
return outputCell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = view.frame.width
let height = view.frame.height - (heightNavigationBarTop + label.frame.height + topSafeArea + tabBarHeight)
let output = Utility.shared.CGSizeMake(width, height)
return output
}
}
class BaseCell: UICollectionViewCell {
override init(frame: CGRect) {
super .init(frame: frame)
setUpViews()
}
func setUpViews() {
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been impemented")
}
}
class CoinCVCCell: BaseCell {
var content: Content? {
didSet{
backgroundColor = content?.color
}
}
}
class Content {
var name: String?
var color: UIColor?
init(name: String, color: UIColor) {
self.name = name
self.color = color
}
}
final class Utility: NSObject {
private override init() { }
static let shared = Utility()
func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
return CGRect(x: x, y: y, width: width, height: height)
}
func CGSizeMake( _ width:CGFloat, _ height:CGFloat) -> CGSize{
return CGSize(width: width, height: height)
}
}
我不明白为什么 collectionView 不适合空间,以及为什么会出现边距,因为我从视图的总高度中减去了视图上不同元素的高度.
I do not understand why the collectionView does not fit in to the space, and why the margins occur, because I subtract the height of the different elements on the view from the total height of the view.
private let reUseIdentifierCollectionView = "CollectionViewCell1"
class CVControllerViewController: UIViewController {
var heightNavigationBarTop: CGFloat{
get{
let barHeight = self.navigationController?.navigationBar.frame.height ?? 0
let statusBarHeight = UIApplication.shared.isStatusBarHidden ? CGFloat(0) : UIApplication.shared.statusBarFrame.height
return barHeight + statusBarHeight
}
}
//Here I am getting the SafeArea above the NavigationBar
var topSafeArea: CGFloat{
get{
var topSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = view.safeAreaInsets.top
} else {
topSafeArea = topLayoutGuide.length
}
return topSafeArea
}
}
var tabBarHeight: CGFloat{ get{ return (self.tabBarController?.tabBar.frame.height)! } }
lazy var label: UILabel = {
let lb = UILabel()
//lb.frame = CGRect(x: 0, y: heightNavigationBarTop + topSafeArea, width: view.frame.width, height: 50)
lb.backgroundColor = .red
return lb
}()
var collectionView: UICollectionView!
var content = [Int: Any]()
override func viewDidLoad() {
super.viewDidLoad()
loadContent()
loadCollectionView()
setLayout()
// view.addSubview(label)
// view.addSubview(collectionView)
}
func setLayout(){
view.sv(label, collectionView)
view.layout(
heightNavigationBarTop,
|-label-| ~ 80,
0,
|collectionView|,
tabBarHeight
)
}
func loadCollectionView() {
let layout = UICollectionViewFlowLayout()
let frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
collectionView = UICollectionView(frame: frame, collectionViewLayout: layout)
collectionView.backgroundColor = .white
collectionView.register(CoinCVCCell.self, forCellWithReuseIdentifier: reUseIdentifierCollectionView)
collectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.scrollDirection = .horizontal
flowLayout.minimumLineSpacing = 0
}
collectionView.delegate = self
collectionView.dataSource = self
}
func loadContent() {
content[0] = Content(name: "Blau", color: .blue)
content[1] = Content(name: "Grün", color: .green)
content[2] = Content(name: "Gelb", color: .yellow)
content[3] = Content(name: "brown", color: .brown)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension CVControllerViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let outputCell: UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseIdentifierCollectionView, for: indexPath) as! CoinCVCCell
cell.content = (content[indexPath.item] as! Content)
outputCell = cell
return outputCell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = view.frame.width
let height = view.frame.height - (tabBarHeight + label.frame.height + heightNavigationBarTop)
let output = Utility.shared.CGSizeMake(width, height)
return output
}
}
我正在使用框架 Stevia,基本上 sv 所做的是设置子视图并将translatesAutoresizingMaskIntoConstraints"设置为 false.通过布局,我正在设置约束,解决方案现在可以满足我的要求,但这是您推荐的方式吗?
I am using the framework Stevia, basically what sv does is setting an subview and setting "translatesAutoresizingMaskIntoConstraints" to false.With layout I am setting the constraints, the solution now does what I want but is that the way you recommended?
func collectionView(_ collectionView: UICollectionView, layoutcollectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath:索引路径) ->
这里我仍然使用框架,这有意义吗?
Here I still use the frame, does that make sense?
推荐答案
但您不知道视图的总高度.那就是问题所在.
But you don’t know the total height of the view. That’s the problem.
您正在viewDidLoad
中调用loadCollectionView
.这还为时过早,因为还没有正确的frame
.因此,您基于其他事物的 frame
计算集合视图的 frame
的所有计算都是不正确的.
You are calling loadCollectionView
in viewDidLoad
. That is way too early, because nothing has its correct frame
yet. Therefore all your calculations to calculate the frame
of the collection view, based on the frame
of other things, are incorrect.
您可以通过等到 viewDidLayoutSubviews
调用 loadCollectionView
来解决此问题,但不要这样做.你根本不应该计算帧!相反,用自动布局做所有事情,让自动布局引擎为你做布局.这样,您就可以在 viewDidLoad
中进行构建,而无需使用任何 frame
值.
You could solve this by waiting until viewDidLayoutSubviews
to call loadCollectionView
, but don't. You shouldn't be calculating frames at all! Instead, do everything with autolayout and let the autolayout engine do the layout for you. That way, you can do the construction in viewDidLoad
without any frame
values coming into play.
这篇关于以编程方式将 collectionView 置于视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!