[英]About auto layouts
因為我已經為集合視圖提供了自動布局,但是在肖像中它很好:
問題在於,隨着景觀的出現,細胞之間的差距正在擴大。 怎么避免這個?
import UIKit
class ViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
@IBOutlet weak var collectionView: UICollectionView!
var images = ["apple","banana","cherry","grapes","kiwifruit","mangoes","orange","papaya","passionfruit","peaches","pineapple","strawberry","sugarapple","watermelon"]
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged(notification:)), name: Notification.Name.UIDeviceOrientationDidChange, object: nil)
collectionView.dataSource = self
collectionView.delegate = self
}
func orientationChanged(notification: Notification) {
collectionView.collectionViewLayout.invalidateLayout()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "stridentifier",for:indexPath) as! FruitsCollectionViewCell
cell.image.image = UIImage(named: images[indexPath.row])
cell.nameLabel.text = images[indexPath.row]
return cell
}
class SampleCollectionViewFlowLayout: UICollectionViewFlowLayout {
override init() {
super.init()
setUpLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpLayout()
}
override var itemSize: CGSize {
set {}
get {
let itemWidth = ((self.collectionView?.bounds.width)! / 3.0) - self.minimumLineSpacing - minimumInteritemSpacing
return CGSize(width: itemWidth, height: itemWidth)
}
}
func setUpLayout() {
minimumInteritemSpacing = 0
minimumLineSpacing = 1.0
scrollDirection = .vertical
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
}
如果您已經子類化了UICollectionViewFlowLayout,則需要覆蓋itemSize
並設置minimumInteritemSpacing
, minimumLineSpacing
一旦您完成了方向更改,您需要告訴集合視圖使用collectionView.collectionViewLayout.invalidateLayout()
重置布局如果您還沒有子類化它你需要覆蓋
collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
每當設備旋轉時調用collectionView.collectionViewLayout.invalidateLayout()
您將不得不為設備旋轉添加通知。
以下是3列的示例UICollectionViewFlowLayout
class SampleCollectionViewFlowLayout: UICollectionViewFlowLayout {
override init() {
super.init()
setUpLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpLayout()
}
override var itemSize: CGSize {
set {}
get {
// 2 columns in portrait and 3 in landscape
if UIApplication.shared.statusBarOrientation.isPortrait {
let itemWidth = ((self.collectionView?.bounds.width)! / 2.0) - self.minimumLineSpacing - minimumInteritemSpacing
return CGSize(width: itemWidth, height: itemWidth)
}
let itemWidth = ((self.collectionView?.bounds.width)! / 3.0) - self.minimumLineSpacing - minimumInteritemSpacing
return CGSize(width: itemWidth, height: itemWidth)
}
}
func setUpLayout() {
minimumInteritemSpacing = 0
minimumLineSpacing = 1.0
scrollDirection = .vertical
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
在viewDidLoad
添加此行
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged(notification:)), name: Notification.Name.UIDeviceOrientationDidChange, object: nil)
並添加功能
func orientationChanged(notification: Notification) {
collectionView.collectionViewLayout.invalidateLayout()
}
此外,如果您使用customLayout,則需要轉到xib->選擇collectionView-> attributes檢查器(第四個選項) - >點擊布局並選擇自定義並在我們的示例中放置子類UICollectionViewLayout類的名稱(SampleCollectionViewFlowLayout)。
在Storyboard / xib文件中選擇UICollectionView后,需要在此處設置UICollectionViewFlowLayout類
雖然我在這個帖子中有點遲了。但我的解決方案將根據您的規范在每個設備中工作。 2個單元格為縱向,3個單元格為橫向。但您可以根據您的選擇增加單元格數量,只需修改NUMBER_OF_CELLS_IN_PORTRAIT和NUMBER_OF_CELLS_IN_LANDSCAPE
我已經在每個功能上發表評論。所以這可能是可以理解的。
起初我做了一些默認值。
let SCREEN_WIDTH = UIScreen.main.bounds.size.width
let SCREEN_HEIGHT = UIScreen.main.bounds.size.height
let BASE_SCREEN_HEIGHT:CGFloat = 736.0
let SCREEN_MAX_LENGTH = max(SCREEN_WIDTH, SCREEN_HEIGHT)
let ASPECT_RATIO_RESPECT_OF_7P = SCREEN_MAX_LENGTH / BASE_SCREEN_HEIGHT
let MINIMUM_INTERITEM_SPACING:CGFloat = 14.0 //My Default Inter Cell Spacing for iphone 7plus as i have designed in it.
var ITEM_WIDTH:CGFloat = 200 //for iPhone 7 plus.initial value
var ITEM_HEIGHT:CGFloat = 200 //for iphone 7 plus.initial value
let NUMBER_OF_CELLS_IN_PORTRAIT:CGFloat = 2
let NUMBER_OF_CELLS_IN_LANDSCAPE:CGFloat = 3
然后在viewDidLoad中使用以下函數初始化集合視圖
func initialCollectionData() {
let orientation = UIApplication.shared.statusBarOrientation
if orientation == .portrait {
self.calculateCellSize(screenWidth:SCREEN_WIDTH ,cellItem: NUMBER_OF_CELLS_IN_PORTRAIT)
}
else {
self.calculateCellSize(screenWidth:SCREEN_WIDTH ,cellItem: NUMBER_OF_CELLS_IN_LANDSCAPE)
}
}
並且有一些輔助功能。 像這樣。
//This method calculate cellsize according to cell number.
func calculateCellSize(screenWidth:CGFloat , cellItem:CGFloat) {
ITEM_WIDTH = (screenWidth - MINIMUM_INTERITEM_SPACING * ASPECT_RATIO_RESPECT_OF_7P * (cellItem-1)) / cellItem - 1// This 1 has been subtracted from ITEM_WIDTH to remove mantissa
ITEM_HEIGHT = ITEM_WIDTH
}
//This method calculate cell number according to orientation.
func findCellItem(screenWidth:CGFloat) {
let orientation = UIDevice.current.orientation
if orientation == .portrait {
self.calculateCellSize(screenWidth:screenWidth ,cellItem: NUMBER_OF_CELLS_IN_PORTRAIT) //You have chosen 2 cells to show in portrait
}
else {
self.calculateCellSize(screenWidth:screenWidth ,cellItem: NUMBER_OF_CELLS_IN_LANDSCAPE) ////You have chosen 3 cells to show in portrait
}
}
//During orientation change this method is called everytime.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { context in
context.viewController(forKey: UITransitionContextViewControllerKey.from)
//Below two methods do the trick
self.findCellItem(screenWidth: size.width)
self.collectionView.collectionViewLayout.invalidateLayout()
}, completion: {
_ in
})
}
//集合查看委托方法
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let collectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
collectionCell.fruitImage.image = UIImage.init(named: imageArray[indexPath.row])
return collectionCell
}
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize.init(width: ITEM_WIDTH , height: ITEM_HEIGHT )
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return MINIMUM_INTERITEM_SPACING * ASPECT_RATIO_RESPECT_OF_7P
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return MINIMUM_INTERITEM_SPACING * ASPECT_RATIO_RESPECT_OF_7P
}
只需在ViewController中添加以下行:
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
self.yourCollectionView.collectionViewLayout.invalidateLayout()
}
並在此委托方法中設置適當的大小:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.