关于汽车布局

时间:2017-04-26 09:04:10

标签: ios swift swift3 autolayout

由于我已经为集合视图提供了自动布局,但是在纵向中它很好:

as I have given auto layout for the collection view but in portrait it was fine

问题在于,随着景观的出现,细胞之间的差距正在扩大。怎么避免这个?

the problem is that where as coming to landscape the gap between the cells are increasing how to avoid this ?

{{1}}

3 个答案:

答案 0 :(得分:1)

如果你有UICollectionViewFlowLayout的子类,你需要覆盖itemSize并设置minimumInteritemSpacingminimumLineSpacing一旦你改变了方向,你需要告诉集合视图重置布局运用 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->属性检查器(第4个选项) - >点击布局并选择自定义,然后在我们的例子中输入子类UICollectionViewLayout类的名称(SampleCollectionViewFlowLayout)。

在Storyboard / xib文件中选择UICollectionView后,需要在此处设置UICollectionViewFlowLayout类

enter image description here

答案 1 :(得分:0)

虽然我在这个帖子中有点迟了。但我的解决方案将根据您的规范在每个设备中运行。 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
}

答案 2 :(得分:-1)

只需在ViewController中添加以下行:

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    self.yourCollectionView.collectionViewLayout.invalidateLayout()
}

并在此委托方法中设置适当的大小:

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {