2つのCollectionView Controllerを備えたViewControllerがあります。
回転では、コレクションビューの1つだけがカスタムサイズにサイズ変更され、もう1つは同じままになります。
私は使用しようとしました:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Adjust cell size for orientation
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
return CGSizeMake(170.f, 170.f);
}
return CGSizeMake(192.f, 192.f);
}
ただし、それは両方のコレクションビューを変更するだけです。 1つのコレクションのみに特定するにはどうすればよいですか?
Heres my 2 cents-あなたのアイテムのサイズは静的なので、なぜcollectionViewLayout
にアイテムのサイズを設定しないのですか?
コレクションビューがすべてのセルに対してデリゲートメソッドを呼び出すことを期待するよりも、これを行う方が迅速です。
viewWillLayoutSubviews
は、View Controllerでの回転の検出に使用できます。 invalidateLayout
をコレクションビューレイアウトで使用して、レイアウトを再度準備し、この場合、新しいサイズで要素を配置することができます。
- (void)viewWillLayoutSubviews;
{
[super viewWillLayoutSubviews];
UICollectionViewFlowLayout *flowLayout = (id)self.firstCollectionView.collectionViewLayout;
if (UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) {
flowLayout.itemSize = CGSizeMake(170.f, 170.f);
} else {
flowLayout.itemSize = CGSizeMake(192.f, 192.f);
}
[flowLayout invalidateLayout]; //force the elements to get laid out again with the new size
}
編集:Swift2.0の例で更新
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
return
}
if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
flowLayout.itemSize = CGSize(width: 170, height: 170)
} else {
flowLayout.itemSize = CGSize(width: 192, height: 192)
}
flowLayout.invalidateLayout()
}
iOS 8を使用しているため、新しいAPIを使用:
スウィフト3:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateCollectionViewLayout(with: size)
}
private func updateCollectionViewLayout(with size: CGSize) {
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode
layout.invalidateLayout()
}
}
Objective-C:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self updateCollectionViewLayoutWithSize:size];
}
- (void)updateCollectionViewLayoutWithSize:(CGSize)size {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode;
[layout invalidateLayout];
}
検証済みの回答は効率的ではありません
問題-viewWillLayoutSubviews()のレイアウトを無効にするのは大変な作業です。 viewWillLayoutSubviews()は、ViewControllerがインスタンス化されると複数回呼び出されます。
My Solution(Swift)-UICollectionViewDelegateFlowLayout内にサイズ操作を埋め込みます。
// Keep a local property that we will always update with the latest
// view size.
var updatedSize: CGSize!
// Use the UICollectionViewDelegateFlowLayout to set the size of our
// cells.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
// We will set our updateSize value if it's nil.
if updateSize == nil {
// At this point, the correct ViewController frame is set.
self.updateSize = self.view.frame.size
}
// If your collectionView is full screen, you can use the
// frame size to judge whether you're in landscape.
if self.updateSize.width > self.updateSize.height {
return CGSize(width: 170, 170)
} else {
return CGSize(width: 192, 192)
}
}
// Finally, update the size of the updateSize property, every time
// viewWillTransitionToSize is called. Then performBatchUpdates to
// adjust our layout.
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
self.updateSize = size
self.collectionView!.performBatchUpdates(nil, completion: nil)
}
Ifステートメントを変更できます。コレクションビューへの参照が必要になります
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && collectionView == self.firstCollectionView) {
return CGSizeMake(170.f, 170.f);
}
問題は、sizeForItemAtIndexPathで2つのコレクションビューを分離する方法でした。なぜこのようなものではないのですか?
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if collectionView == firstCollectionView{
return CGSize(width: self.frame.width/3, height: 40)
}
else if collectionView == secondCollectionView{
return CGSize(width: self.frame.width, height: self.frame.height-2)
}
abort()
}
デバイスの回転を確認し、レイアウトを再読み込みすることで、この問題を解決しました。画面サイズを確認し、このサイズを使用してセルを表示します。
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
//get new width of the screen
screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
//if landscape mode
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
screenDivide = 5;
}
else
{
screenDivide = 3;
}
//reload the collectionview layout after rotating
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
[layout invalidateLayout];
}
次に、このようにセルを定義しました
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
CGSize elementSize = CGSizeMake(screenWidth/screenDivide, 100);
return elementSize;
}