關于圖片輪播的問題(UICollectionView初始化滾動到中間)

轉自:
http://www.wossoneri.com/2016/01/21/[iOS]%20UICollectionView%E5%88%9D%E5%A7%8B%E5%8C%96%E6%BB%9A%E5%8A%A8%E5%88%B0%E4%B8%AD%E9%97%B4/

demo是封裝了一個控件,直接在MainViewController
的viewWillAppear里初始化,并且調用一個初始化滾動到中間的方法,方法主要是調用了
-(void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;

方法,在初始化后將其滾動到中間的區域。不過,當我在項目里使用的時候,遇到了調用該方法卻無法滾動到中間的情況。我的使用步驟是:在我界面的UIView
中,創建該控件對象并且調用滾動到中間的方法。
scrollToItemAtIndexPath使用
發現效果無法實現,我第一時間檢查了函數有沒有調用,然后發現是調用的了,但沒有出現該出現的效果。所以簡單看一下該方法的官方注釋。xcode提示的描述是:Scrolls the collection view contents until the specified item is visible.
只是方法的作用,并沒有說使用條件。為了快速解決問題,google了一下scrolltoitematindexpath not working
,在這里:link找到了答案:
不知道這是一個bug還是一個特性,每當在UICollectionView
顯示它的subview
之前調用scrollToItemAtIndexPath:atScrollPosition:Animated
方法,UIKit就會報錯。所以要解決它,就應該在viewController
中,在你能確認CollectionView
完全計算出其subview
布局的地方去調用這個方法。比如在viewDidLayoutSubviews
里調用就沒有問題。

方法的意思已經明確,就是找到一個能計算出collectionview
的所有布局地方調用滾動方法。但我的界面使用的是自動布局,只在模塊外有一個viewController
,其余的都是在UIView
中創建添加,所以在我使用這個控件對象的地方,我無法復寫viewController
的方法。所以想了幾個辦法。

-layoutsubviews
既然情況發生在UIView
中,那首先想到的是重寫該方法。重寫之前,看一下文檔說明:
Lays out subviews.
DiscussionThe default implementation of this method does nothing on iOS 5.1 and earlier. Otherwise, the default implementation uses any constraints you have set to determine the size and position of any subviews.

Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.
You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.
該方法為子view布局。子類可以復寫該方法為子view實現更精確的布局。但你只應該在用自動布局時無法實現效果時用它。而且你不應該直接調用該方法,如果需要強制刷新布局,調用setNeedLayout
,會在下一次繪制刷新前更新布局。調用layoutIfNeed
可以立即刷新布局。
看起來這個方法有用,我便試了一下。

[self setNeedLayout];
[self layoutIfNeed];
[myPicker scrollToCenter];

然而還是沒有效果。

[view.window]

前面的方法沒效果,我又想了一下scrolltoitematindexpath
的實現條件,是在UICollectionView
顯示之后調用才有效,所以我需要在UIView中獲得它顯示的狀態再去滾動。幸好,我的控件也是繼承UIView的,其中有這么一個屬性:
Property: windowThis property is nil if the view has not yet been added to a window.

也就是說這個屬性值代表著這個view
有沒有放在窗口中顯示,那么我就需要在當前UIView
的生命周期中檢查myPicker
對象的這個屬性就好了。所以最后的解決方法是,起一個子線程,對myPicker
的狀態進行檢查,當狀態為顯示的時候調用滾動方法:

NSThread *checkShownThread;
checkShownThread = [[NSThread alloc] initWithTarget:self selector:@selector(checkIfViewIsShowing) object:nil];
[checkShownThread start];

- (void)checkIfViewIsShowing {
   while (1) {
      if (hPicker.window != nil) {
         break;
      }
}

dispatch_async(dispatch_get_main_queue(), ^{
   [hPicker scrollToCenter];
});

[checkShownThread cancel];
checkShownThread = nil;

但不建議開線程(費性能),所以可以外接屬性,在控制器- (void)viewDidLayoutSubviews中去寫該方法

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    [self.rewardHeaderView.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:100/2] atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Documentation Supported OS & SDK Versions 支持的OS & SDK版本 S...
    c5550ea746f8閱讀 4,420評論 0 2
  • UIKit 的 UIView 是一個非常重要的類,幾乎每個嘗試 iOS 開發的程序員都會用到它。UIView 本身...
    haifengmay閱讀 1,661評論 2 9
  • 約酒吟 為祝賀朋友公務員考試得第一所作 苗壯 帽插宮花著紅裝,一舉高中悅賡飏。 樂過...
    苗老師雜談閱讀 292評論 0 0
  • 拖拖拉拉地,終于寫到結語。寫了那么多干貨,卻很少地寫血肉。今天就碎碎念一下這一路遇到的姑娘吧。 聞見玫瑰香在紐約的...
    荒草集閱讀 190評論 0 0
  • 優秀從來都不是說說而已,那是骨子里的一種品質;就那樣吧,順其自然吧,從來都不是一種灑脫。想得當最好的,就得承...
    跳動的指尖閱讀 213評論 0 0