1. 程式人生 > >用KVO監聽實現collectionView滾動一致,完整專案movie

用KVO監聽實現collectionView滾動一致,完整專案movie

效果圖如下:  為使的上面的collectionView的滾動和下面的collectionView的滾動保持一致  先採用 kvo方式

詳情請看程式碼註釋

        //1.kvo監聽模式 option需要新的值還是舊的值
        [_postView addObserver:self forKeyPath:@"currentIndex" options:NSKeyValueObservingOptionNew context:nil];
        [_headerColletion addObserver:self forKeyPath:@"currentIndex" options:NSKeyValueObservingOptionNew context:nil];

其中_postView 是下面的collectionView  headerCollectionView是上面的collectionView  分別監聽他們的currentIndex屬性  currentIndex是標記他在第幾個item上

//1.kvo監聽模式
/**
 keyPath:監聽的屬性名
 object:監聽的物件
 change:監聽的值
 context:傳遞的資料
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    //取得新的值
    NSNumber *value = [change objectForKey:@"new"];
    //轉換為int值
    NSInteger selectIndex = [value intValue];

    //轉換為滾動到的位置書
    NSIndexPath *IndexPath = [NSIndexPath indexPathForItem:selectIndex inSection:0];
    
    //如果監聽的物件是headerView 並且postView的currentIndex 不等於headerViewcell選中的currentIndex那麼 postView 就滾動到選中的item
    if (object == _headerColletion && _postView.currentIndex != selectIndex) {
        
        [_postView scrollToItemAtIndexPath:IndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
        
        //操作完成後把postView的currentIndex 變成這個
        _postView.currentIndex = selectIndex;
        
    //如果監聽的物件是postView 並且headerView的currentIndex 不等於postViewcell選中的currentIndex那麼 postView 就滾動到選中的item
    } else if(object == _postView && _headerColletion.currentIndex != selectIndex){
        
        [_headerColletion scrollToItemAtIndexPath:IndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
        //操作完成後把postView的currentIndex 變成這個
        _headerColletion.currentIndex = selectIndex;
    }

}
這裡的值得一提的事change這個這個值 可以用key new 和old取值  分別取得 新值和舊值
具體可以看註釋  下面是posterView中滾動完成後的呼叫函式屬性currentIndex改變 受到監聽
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
    //因為offset不是物件不能用點訪問
    CGFloat contentX = targetContentOffset->x;
    
    /*round:如果引數是小數,則求本身的四捨五入。
     ceil:如果引數是小數,則求最小的整數但不小於本身.
     floor:如果引數是小數,則求最大的整數但不大於本身.
     
     Example:如何值是3.4的話,則
     3.4 -- round 3.000000
     -- ceil 4.000000
     -- floor 3.00000
     **/
    
    //用四色五入 計算第幾頁
    float pageFloat = contentX/_pageWidth;
    
    NSInteger page = (int)round(pageFloat);
    
    targetContentOffset->x = page * _pageWidth;
    
    //記錄當前頁面 此處要提醒一句  這個值必須要用系統生成的setter語句來賦值才能kvo監聽 _currentIndex = page是不能夠監聽到的
    self.currentIndex = page;

此處要提醒一句這個值必須要用系統生成的setter語句來賦值才能kvo監聽 _currentIndex = page是不能夠監聽到的

當點選了 不是當前的item 那麼也會滾動  currentIndex 也會改變

//單元格點選事件處理
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    
        //滾到點選的cell
    [collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
//    if ([self.scrolldelegate respondsToSelector:@selector(scrollToCurrentIndex:)]) {
//        [self.scrolldelegate scrollToCurrentIndex:indexPath.item];
//    }
    
        
        //記錄當前的cell  此處要提醒一句  這個值必須要用系統生成的setter語句來賦值才能kvo監聽 _currentIndex = indexPath.item是不能夠監聽到的
    self.currentIndex = indexPath.item;
    
    
}

其中註釋部分為代理實現方式  不用理會 如果你想看代理實現方式 可以看下一篇文章

也可以看原始碼 地址點選開啟連結  github上的動畫太卡了  真實沒那麼卡的  你們可以下下來看一下