17

我有很多的困難,努力創造一個UICollectionView像Spotify的播放器,其作用類似於這樣:如何創建一箇中心UICollectionView像Spotify的播放器

a busy cat

,我的問題是雙重的。

1)我如何居中細胞,以便您可以看到中間細胞以及左邊和右邊的一個。

  • 如果我創建正方形的單元格並在每個單元格之間添加間距,則單元格可以正確顯示但不居中。

2)使用pagingEnabled = YES,collectionview會正確地從一個頁面滑動到另一個頁面。但是,如果沒有將單元格居中,它只會將收集視圖移動到屏幕寬度的頁面上。所以問題是你如何讓頁面移動,以獲得上述效果。

3)你怎麼動畫單元的大小,因爲它們移動

  • 我不想爲此擔心太多。如果我能得到那個工作也將是巨大的,但更難的問題是1和2

我目前的代碼是一個簡單的UICollectionView與爲正方形正常委派安裝和自定義UICollectionview細胞。也許我需要子類UICollectionViewFlowLayout?或者,也許我需要將pagingEnabled爲NO,然後使用自定義刷卡事件?會愛任何幫助!

+1

這裏是在Github上找到了一個例子:https://github.com/ikemai/ScaledVisibleCellsCollectionView也許它可以幫助你:) – Lapinou

+0

@Lapinou我有我的目標c項目中使用這個麻煩。似乎不能讓橋接工作 – evenodd

+0

嗯......通常,這很容易。看看這篇文章:http://stackoverflow.com/questions/24206732/cant-use-swift-classes-inside-objective-c讓我知道它是否適合你;) – Lapinou

回答

5

當您在評論說你想,在Objective-C代碼,有一個叫iCarousel非常著名的圖書館,可在完成你的requirement.Link會有所幫助:https://github.com/nicklockwood/iCarousel

您可以使用「旋轉「或‘直線’或一些其他風格很少或根本沒有修改來實現自定義視圖

要實現它,你必須只實現它的一些委託方法,它的工作爲前:

//specify the type you want to use in viewDidLoad 
_carousel.type = iCarouselTypeRotary; 

//Set the following delegate methods 
- (NSInteger)numberOfItemsInCarousel:(iCarousel *)carousel 
{ 
    //return the total number of items in the carousel 
    return [_items count]; 
} 

- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view 
{ 
    UILabel *label = nil; 

    //create new view if no view is available for recycling 
    if (view == nil) 
    { 
     //don't do anything specific to the index within 
     //this `if (view == nil) {...}` statement because the view will be 
     //recycled and used with other index values later 
     view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)]; 
     ((UIImageView *)view).image = [UIImage imageNamed:@"page.png"]; 
     view.contentMode = UIViewContentModeCenter; 

     label = [[UILabel alloc] initWithFrame:view.bounds]; 
     label.backgroundColor = [UIColor clearColor]; 
     label.textAlignment = NSTextAlignmentCenter; 
     label.font = [label.font fontWithSize:50]; 
     label.tag = 1; 
     [view addSubview:label]; 
    } 
    else 
    { 
     //get a reference to the label in the recycled view 
     label = (UILabel *)[view viewWithTag:1]; 
    } 

    //set item label 
    label.text = [_items[index] stringValue]; 

    return view; 
} 

- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value 
{ 
    if (option == iCarouselOptionSpacing) 
    { 
     return value * 1.1; 
    } 
    return value; 
} 

你可以CHEC ķ從包含在Github上庫鏈接

因爲它是舊的和流行的,你可以找到它的一些相關的教程,它也將成爲比自定義代碼實現多穩定「Examples/Basic iOS Example」全面工作演示

14

嗯,我昨天讓UICollectionview像這樣移動。

我可以與大家分享我的代碼:)

這裏是我的故事板

化妝確保取消選中 '尋呼已啓用'

這裏是我的代碼。

@interface FavoriteViewController() <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> 
{ 
    NSMutableArray * mList; 

    CGSize cellSize; 
} 

@property (weak, nonatomic) IBOutlet UICollectionView *cv; 
@end 

@implementation FavoriteViewController 

- (void) viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    // to get a size. 
    [self.view setNeedsLayout]; 
    [self.view layoutIfNeeded]; 

    CGRect screenFrame = [[UIScreen mainScreen] bounds]; 
    CGFloat width = screenFrame.size.width*self.cv.frame.size.height/screenFrame.size.height; 
    cellSize = CGSizeMake(width, self.cv.frame.size.height); 
    // if cell's height is exactly same with collection view's height, you get an warning message. 
    cellSize.height -= 1; 

    [self.cv reloadData]; 

    // setAlpha is for hiding looking-weird at first load 
    [self.cv setAlpha:0]; 
} 

- (void) viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 

    [self scrollViewDidScroll:self.cv]; 
    [self.cv setAlpha:1]; 
} 

#pragma mark - scrollview delegate 
- (void) scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    if(mList.count > 0) 
    { 
     const CGFloat centerX = self.cv.center.x; 
     for(UICollectionViewCell * cell in [self.cv visibleCells]) 
     { 
      CGPoint pos = [cell convertPoint:CGPointZero toView:self.view]; 
      pos.x += cellSize.width/2.0f; 
      CGFloat distance = fabs(centerX - pos.x); 

// If you want to make side-cell's scale bigger or smaller, 
// change the value of '0.1f' 
      CGFloat scale = 1.0f - (distance/centerX)*0.1f; 
      [cell setTransform:CGAffineTransformMakeScale(scale, scale)]; 
     } 
    } 
} 

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 
{ // for custom paging 
    CGFloat movingX = velocity.x * scrollView.frame.size.width; 
    CGFloat newOffsetX = scrollView.contentOffset.x + movingX; 

    if(newOffsetX < 0) 
    { 
     newOffsetX = 0; 
    } 
    else if(newOffsetX > cellSize.width * (mList.count-1)) 
    { 
     newOffsetX = cellSize.width * (mList.count-1); 
    } 
    else 
    { 
     NSUInteger newPage = newOffsetX/cellSize.width + ((int)newOffsetX%(int)cellSize.width > cellSize.width/2.0f ? 1 : 0); 
     newOffsetX = newPage*cellSize.width; 
    } 

    targetContentOffset->x = newOffsetX; 
} 

#pragma mark - collectionview delegate 
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 
    return mList.count; 
} 
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UICollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"list" forIndexPath:indexPath]; 

    NSDictionary * dic = mList[indexPath.row]; 

    UIImageView * iv = (UIImageView *)[cell.contentView viewWithTag:1]; 
    UIImage * img = [UIImage imageWithData:[dic objectForKey:kKeyImg]]; 
    [iv setImage:img]; 

    return cell; 
} 

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return cellSize; 
} 
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section 
{ 
    CGFloat gap = (self.cv.frame.size.width - cellSize.width)/2.0f; 
    return UIEdgeInsetsMake(0, gap, 0, gap); 
} 
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section 
{ 
    return 0; 
} 
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section 
{ 
    return 0; 
} 

居中化妝單元的鍵碼是

  1. scrollViewWillEndDragging

  2. insetForSectionAtIndex

動畫的

關鍵碼的大小是

  1. scrollviewDidScroll

我希望這可以幫助你

附: 如果你想改變阿爾法就像你上傳的圖片,在scrollViewDidScroll添加[細胞setalpha]

+0

感謝您的幫助代碼 –

1

pagingEnabled不應該,因爲它需要每個單元是您查看,不會因爲你的工作寬度啓用你需要看到其他單元格的邊緣。對於你的第一點和第二點。我想你會從我對另一個問題的遲到答案中找到你需要的東西here

可以通過繼承UIcollectionviewFlowLayout並覆蓋layoutAttributesForItemAtIndexPath:來實現單元尺寸的動畫。修改通過首先調用super提供的佈局屬性,然後根據與窗口中心相關的位置修改佈局屬性大小。

希望這會有所幫助。

5

我希望稍微有點類似的行爲,在@Mike_M的幫助下,我能夠弄明白。雖然有很多很多方法可以做到這一點,但這個特定的實現是創建一個自定義的UICollectionViewLayout。下面

代碼(GIST可以在這裏找到:https://gist.github.com/mmick66/9812223

現在設置下列事項:*yourCollectionView*.decelerationRate = UIScrollViewDecelerationRateFast,這可以防止通過快速輕掃被跳過的細胞。

這應該包括第1部分和第2部分。現在,對於第3部分,您可以通過不斷的無效化和更新將它合併到自定義collectionView中,但是如果你問我,這有點麻煩。因此,另一種方法是在UIScrollViewDidScroll中設置CGAffineTransformMakeScale(,),您可以根據它與屏幕中心的距離動態更新單元格的大小。

您可以使用[*youCollectionView indexPathsForVisibleItems]獲取collectionView的可見單元格的indexPaths,然後獲取這些indexPaths的單元格。對於每一個細胞,計算出的中心yourCollectionView

中的CollectionView的中心可以使用這個漂亮的方法來發現其中心的距離:CGPoint point = [self.view convertPoint:*yourCollectionView*.center toView:*yourCollectionView];

現在成立了一個規則,如果小區的中心比x更遠,單元格的大小例如是'正常大小',稱爲1.並且它越接近中心,它越接近正常大小2的兩倍。

然後你可以使用以下if/else的想法:

if (distance > x) { 
     cell.transform = CGAffineTransformMakeScale(1.0f, 1.0f); 
} else if (distance <= x) { 

     float scale = MIN(distance/x) * 2.0f; 
     cell.transform = CGAffineTransformMakeScale(scale, scale); 
} 

會發生什麼情況是,單元格的大小將完全按照您的觸摸。讓我知道你是否有更多的問題,因爲我寫的大部分內容都是從我頭頂開始的)。

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)offset 
          withScrollingVelocity:(CGPoint)velocity { 

CGRect cvBounds = self.collectionView.bounds; 
CGFloat halfWidth = cvBounds.size.width * 0.5f; 
CGFloat proposedContentOffsetCenterX = offset.x + halfWidth; 

NSArray* attributesArray = [self layoutAttributesForElementsInRect:cvBounds]; 

UICollectionViewLayoutAttributes* candidateAttributes; 
for (UICollectionViewLayoutAttributes* attributes in attributesArray) { 

    // == Skip comparison with non-cell items (headers and footers) == // 
    if (attributes.representedElementCategory != 
     UICollectionElementCategoryCell) { 
     continue; 
    } 

    // == First time in the loop == // 
    if(!candidateAttributes) { 
     candidateAttributes = attributes; 
     continue; 
    } 

    if (fabsf(attributes.center.x - proposedContentOffsetCenterX) < 
     fabsf(candidateAttributes.center.x - proposedContentOffsetCenterX)) { 
     candidateAttributes = attributes; 
    } 
} 

return CGPointMake(candidateAttributes.center.x - halfWidth, offset.y); 

} 
相關問題