我想在我的應用程序中實現「卡片」,如Safari選項卡或App Store搜索。UICollectionView:像Safari選項卡或App Store搜索一樣分頁
我會在屏幕的中心顯示用戶一張牌,並在左右兩側顯示前一張和下一張牌的一部分。 (請參閱App Store搜索或Safari標籤爲例)
我決定使用UICollectionView
,我需要更改頁面大小(沒有找到如何)或實現自己的佈局子類(不知道如何)?
請幫忙嗎?
我想在我的應用程序中實現「卡片」,如Safari選項卡或App Store搜索。UICollectionView:像Safari選項卡或App Store搜索一樣分頁
我會在屏幕的中心顯示用戶一張牌,並在左右兩側顯示前一張和下一張牌的一部分。 (請參閱App Store搜索或Safari標籤爲例)
我決定使用UICollectionView
,我需要更改頁面大小(沒有找到如何)或實現自己的佈局子類(不知道如何)?
請幫忙嗎?
下面是我發現得到這種效果的最簡單的方法。它涉及你的收藏視圖和一個額外的祕密滾動視圖。
設置您收集意見
將集合視圖的contentInset
:
_collectionView.contentInset = UIEdgeInsetsMake(0, (self.view.frame.size.width-pageSize)/2, 0, (self.view.frame.size.width-pageSize)/2);
這有助於抵消正常細胞。
設置你的祕密滾動型
hidden
。contentSize
設置爲您的收藏視圖的預期內容大小。移動你的手勢識別
祕密滾動型的手勢識別添加到集合視圖,並禁用集合視圖的手勢識別:
[_collectionView addGestureRecognizer:_secretScrollView.panGestureRecognizer];
_collectionView.panGestureRecognizer.enabled = NO;
代表
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint contentOffset = scrollView.contentOffset;
contentOffset.x = contentOffset.x - _collectionView.contentInset.left;
_collectionView.contentOffset = contentOffset;
}
隨着scrollview的移動,獲取其偏移量並將其設置爲集合視圖的偏移量。
我的博客上講述這個在這裏,所以檢查此鏈接更新:http://khanlou.com/2013/04/paging-a-overflowing-collection-view/
以前是相當複雜的,UICollectionView是的UIScrollView的子類,所以只是這樣做:
[self.collectionView setPagingEnabled:YES];
你們都是設置去。
看到這個detailed tutorial。
這並沒有解決分頁時可以看到左側和右側內容的問題,如Safari瀏覽器標籤或應用商店搜索。 –
Soroush答案的一個小編輯,這對我來說伎倆。 我做的,而不是禁用手勢唯一編輯:
[_collectionView addGestureRecognizer:_secretScrollView.panGestureRecognizer];
_collectionView.panGestureRecognizer.enabled = NO;
我上的CollectionView禁用滾動:
_collectionView.scrollEnabled = NO;
由於禁用禁用祕密滾動型手勢以及手勢。
你也可以繼承UICollectionViewFlowLayout並重寫,像這樣:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)contentOffset
withScrollingVelocity:(CGPoint)velocity
{
NSArray* layoutAttributesArray =
[self layoutAttributesForElementsInRect:self.collectionView.bounds];
if(layoutAttributesArray.count == 0)
return contentOffset;
UICollectionViewLayoutAttributes* candidate =
layoutAttributesArray.firstObject;
for (UICollectionViewLayoutAttributes* layoutAttributes in layoutAttributesArray)
{
if (layoutAttributes.representedElementCategory != UICollectionElementCategoryCell)
continue;
if((velocity.x > 0.0 && layoutAttributes.center.x > candidate.center.x) ||
(velocity.x <= 0.0 && layoutAttributes.center.x < candidate.center.x))
candidate = layoutAttributes;
}
return CGPointMake(candidate.center.x - self.collectionView.bounds.size.width * 0.5f, contentOffset.y);
}
這將讓根據車速下一個或前一個單元格...它不會對當前單元格對齊但是。
我會添加另一個解決方案。捕捉到的位置並不完美(不如啓用分頁功能時效果不錯,但效果不錯)。
我嘗試過實施Soroush的解決方案,但它不適用於我。
由於UICollectionView
是UIScrollView
一個子類它將一個重要UIScrollViewDelegate
方法,其是響應:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
的targetContentOffset
(一個INOUT指針),可以重新定義爲一個集合視圖停止點(在這種情況下,如果您水平滑動,則爲x
)。
約上幾個變量的快速說明如下發現:
self.cellWidth
- 這是您的收藏觀察室的寬度(如果你願意,你甚至可以硬編碼有)
self.minimumLineSpacing
- 這是您在單元格之間設置的最小行間距
self.scrollingObjects
是集合視圖中包含的對象數組(我需要此主要用於算,知道什麼時候該停止滾動)
所以,這個想法是落實在集合視圖的委託這種方法,像這樣:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
{
if (self.currentIndex == 0 && velocity.x < 0) {
// we have reached the first user and we're trying to go back
return;
}
if (self.currentIndex == (self.scrollingObjects.count - 1) && velocity.x > 0) {
// we have reached the last user and we're trying to go forward
return;
}
if (velocity.x < 0) {
// swiping from left to right (going left; going back)
self.currentIndex--;
} else {
// swiping from right to left (going right; going forward)
self.currentIndex++;
}
float xPositionToStop = 0;
if (self.currentIndex == 0) {
// first row
xPositionToStop = 0;
} else {
// one of the next ones
xPositionToStop = self.currentIndex * self.cellWidth + (self.currentIndex + 1) * self.minimumLineSpacing - ((scrollView.bounds.size.width - 2*self.minimumLineSpacing - self.cellWidth)/2);
}
targetContentOffset->x = xPositionToStop;
NSLog(@"Point of stopping: %@", NSStringFromCGPoint(*targetContentOffset));
}
期待你的任何反饋,使捕捉更好。我還會繼續尋找更好的解決方案......在斯威夫特
這似乎工作...但不能精確複製「分頁啓用」,感覺有點尷尬。 –
@Mike M's answer ...
class CenteringFlowLayout: UICollectionViewFlowLayout {
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView,
let layoutAttributesArray = layoutAttributesForElementsInRect(collectionView.bounds),
var candidate = layoutAttributesArray.first else { return proposedContentOffset }
layoutAttributesArray.filter({$0.representedElementCategory == .Cell }).forEach { layoutAttributes in
if (velocity.x > 0 && layoutAttributes.center.x > candidate.center.x) ||
(velocity.x <= 0 && layoutAttributes.center.x < candidate.center.x) {
candidate = layoutAttributes
}
}
return CGPoint(x: candidate.center.x - collectionView.bounds.width/2, y: proposedContentOffset.y)
}
}
然而,這並不正確傳通過對底層集合視圖iOS7的選擇並點擊事件。有任何想法嗎? – eanticev
在iOS7上(至少 - 在此之前可能是真的),你不需要滾動視圖。只需檢測左右滑動手勢,並使用它們將集合視圖的偏移設置爲前後1頁。 – buildsucceeded
我不能爲了我的生活讓它在iOS7上工作。 「祕密」滾動視圖的「scrollViewDidScroll」永遠不會被傳送。 –