以编程方式将 collectionView 置于视图中
Programmatically placing collectionView in view
我想以编程方式在底部的导航栏、标签和选项卡栏之间放置一个 collectionView。
我不希望不同部分之间有任何间距,如何正确地将视图添加到视图中?最好的方法是什么?
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 不适合 space,以及为什么会出现边距,因为我从视图的总高度中减去了视图上不同元素的高度。
编辑:
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。
通过布局我正在设置约束,解决方案现在可以满足我的要求,但这是您推荐的方式吗?
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath:
IndexPath) ->
这里我还是用frame,有道理吗?
以编程方式:
设置 sectionInset 并使布局无效
或
在集合视图尺寸检查器中将底部和顶部的部分插入设置为0
ColectionView Section Inset
because I subtract the height of the different elements on the view from the total height of the view
但是您不知道视图的总高度。那就是问题所在。
您正在 viewDidLoad
中呼叫 loadCollectionView
。那还为时过早,因为还没有正确的 frame
。因此,您根据其他事物的 frame
计算集合视图的 frame
的所有计算都是不正确的。
您可以等到 viewDidLayoutSubviews
后再调用 loadCollectionView
来解决此问题,但请不要这样做。你根本不应该计算帧!相反,使用自动布局完成所有操作,让自动布局引擎为您完成布局。这样,您可以在 viewDidLoad
中进行构造,而无需任何 frame
值发挥作用。
我想以编程方式在底部的导航栏、标签和选项卡栏之间放置一个 collectionView。
我不希望不同部分之间有任何间距,如何正确地将视图添加到视图中?最好的方法是什么?
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 不适合 space,以及为什么会出现边距,因为我从视图的总高度中减去了视图上不同元素的高度。
编辑:
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。 通过布局我正在设置约束,解决方案现在可以满足我的要求,但这是您推荐的方式吗?
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) ->
这里我还是用frame,有道理吗?
以编程方式: 设置 sectionInset 并使布局无效
或
在集合视图尺寸检查器中将底部和顶部的部分插入设置为0
ColectionView Section Inset
because I subtract the height of the different elements on the view from the total height of the view
但是您不知道视图的总高度。那就是问题所在。
您正在 viewDidLoad
中呼叫 loadCollectionView
。那还为时过早,因为还没有正确的 frame
。因此,您根据其他事物的 frame
计算集合视图的 frame
的所有计算都是不正确的。
您可以等到 viewDidLayoutSubviews
后再调用 loadCollectionView
来解决此问题,但请不要这样做。你根本不应该计算帧!相反,使用自动布局完成所有操作,让自动布局引擎为您完成布局。这样,您可以在 viewDidLoad
中进行构造,而无需任何 frame
值发挥作用。