2013-05-02 31 views
22

我有一個帶有UICollectionViewFlowLayout的UICollectionView。我也實現了UICollectionViewDelegateFlowLayout協議。UICollectionViewFlowLayout不會導致方向更改無效

在我的數據源中,我有一堆UIViewControllers響應自定義協議,所以我可以問他們的大小和一些其他的東西。

在FlowLayout委託中,當它詢問sizeForItemAtIndexPath時,我返回從協議中獲得的項目大小。實現我的協議的ViewControllers根據方向返回不同的項目大小。

現在,如果我設備的方向改變,從縱向到橫向世界上沒有問題(項目在景觀大),但如果我改回來,我得到這樣的警告:

the item width must be less that the width of the UICollectionView minus the section insets left and right values. 
    Please check the values return by the delegate. 

它仍然工作,但我不不喜歡它得到警告,所以也許你可以告訴我我做錯了什麼。還有另一個問題。如果我不告訴我的collectionViewView collectionLayout在willAnimateRotationToInterfaceOrientation中失效:sizeForItemAtIndexPath:永遠不會被調用。

希望你明白我的意思。如果你需要更多的信息,請告訴我:)

+0

我有同樣的問題,你想通了,什麼是錯的? – kevboh 2013-05-15 15:39:27

+0

還沒有,但我仍然在解決方案。如果我找到一個,我會讓你知道 – xxtesaxx 2013-05-17 08:44:26

回答

2

一個解決方案是使用KVO並監聽你的收藏視圖的超視圖框架的變化。調用-reloadData將工作並擺脫警告。這裏有一個潛在的時間問題...

// -loadView 
[self.view addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil]; 

// -dealloc 
[self.view removeObserver:self forKeyPath:@"frame"]; 

// KVO Method 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    [collectionView_ reloadData]; 
} 
+1

這可能工作,但UIView框架不符合KVO每個文檔,Bob Wakefield的答案是獨立於任何黑客。 – myell0w 2014-03-23 11:22:06

35

這個答案很晚,但接受的答案並不適用於我。我希望得到一個難忘的UICollectionViewFlowLayout的OP。我建議視圖控制器中的佈局無效實際上是最好的解決方案。

我想要一個水平滾動的單元格線,集中在視圖中,縱向和橫向。

我分類了UICollectionViewFlowLayout。

我覆蓋了prepareLayout重新計算插入,然後調用[super prepareLayout]。

我覆蓋了getViewContentSize的getter以使確定的內容大小是正確的。

即使邊界隨着重新定向而改變,佈局並沒有自行失效。

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    // does the superclass do anything at this point? 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 

    // do whatever else you need before rotating toInterfaceOrientation 

    // tell the layout to recalculate 
    [self.collectionViewLayout invalidateLayout]; 
} 

UICollectionViewFlowLayout保持方向之間的滾動位置。如果它是正方形的話,相同的單元格將僅以居中

+0

這應該是被接受的答案 – myell0w 2014-03-23 11:22:25

+0

接受的答案 - 在那裏。 – Andrew 2014-08-29 16:48:15

+0

@cynistersix有更現代的答案。旋轉界面已被棄用。我認爲最好是使佈局失效,而不是重新加載數據。 – 2015-04-26 14:20:18

2

我不知道它是否可以幫助某人,但沒有最後一個答案幫助我,因爲我將一些UIViews轉換爲UIScrollView

我打開UIViews編程取決於一些事件。所以我不能使用- (void) willRotateToInterfaceOrientation:invalidateLayoutreloadData,因爲:
1. invalidateLayout「在下一個視圖佈局更新週期中發生」。
2。reloadData「爲了提高效率,收集視圖僅顯示可見的單元格和補充視圖。」

什麼工作對我來說是使用的CollectionView的父(一的UIView)的寬度:

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 
int currentWidth = self.frame.size.width; 

UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)collectionView.collectionViewLayout sectionInset]; 
int fixedWidth = currentWidth - (sectionInset.left + sectionInset.right); 


出於某種原因的CollectionView框架有肖像的寬度的時候調用這個函數。 ..使用int currentWidth = self.frame.width幫助我解決它。

7

我這裏使用的兩個答案的組合做什麼,我們都在努力做的確實是做一個集合視圖看起來像一個表視圖,但不使用的UITableView並在單柱獲得的物品(最有可能)

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { 
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 

    [self.collectionView.collectionViewLayout invalidateLayout]; 
} 
+2

第一棄用我建議你無效,而不是重新加載數據的佈局。 – 2015-06-21 20:35:15

+0

你必須擁有超能力@BobWakefield ...我已經做出了這個改變:)已更新回答 – cynistersix 2015-06-22 21:40:13

1

的@ 0mahc0的回答爲我工作,但只有部分。

我沒有旋轉的問題,因爲我強迫我的應用程序只在人像模式,但我的解決方案可以幫助其他有同樣的問題。

警告顯示每次出現的查看時間。警告的原因非常清楚,我們已經在UICollectionView的左側和右側定義了部分插入。檢查界面構建器,您將在度量中看到定義的這些值。

的@ 0mahc0的解決方案工作,但我想伸展細胞最大寬度,所以我刪除部分的插圖,否則我將有一個「緣」左,右。

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{ 
    return UIEdgeInsetsZero; 
} 

無需實現委託方法的,你可以去建設者和變化值接口到左,右插圖爲零。

+0

在界面生成器中,插值的值爲零,但我仍然收到這個錯誤。 – 2017-09-13 11:07:09

2

iOS8上:我可以沉默警告的唯一方法是調用旋轉到一個更小的尺寸時,旋轉到更大的尺寸和轉型之前,當在過渡期間無效。

self.sizeForCollectionView = size; //used to determine collectionview size in sizeForItem 
    if (size.width <= size.height) { 
     [self.collectionView.collectionViewLayout invalidateLayout]; 
    } 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
     if (size.width > size.height) { 
      [self.collectionView.collectionViewLayout invalidateLayout]; 
     } 
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
    }]; 
+0

不要讓協調器沿着過渡動畫,只需調用invalidateLayout就不適合我。這似乎是 – Craig 2017-02-10 02:52:21

3

上@ meelawsh的答案的變化,但是在斯威夫特,並沒有self.sizeForCollectionView屬性:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) 

    guard let collectionView = self.collectionView else { 
     return 
    } 

    if size.width > collectionView.frame.width { 
     // bigger 

     let animation: (UIViewControllerTransitionCoordinatorContext)->(Void) = { 
      context in 
      collectionView.collectionViewLayout.invalidateLayout() 
     } 

     coordinator.animateAlongsideTransition(animation, completion: nil) 
    } else { 
     // smaller 
     collectionView.collectionViewLayout.invalidateLayout() 
    } 
} 
+0

我實際上並沒有感覺到做'coordinator.animateAlongsideTransition(動畫,完成:無)'的區別。所以我認爲只有'collectionView.collectionViewLayout.invalidateLayout()'應該足夠了。 – Hlung 2016-03-18 06:47:12

相關問題