我必须像Appstore iOS app一样创建网格视图。我想用UICollectionView分页来做这件事。我也实现了代码但不能像那样滚动。
我想要做的是在中心和两侧(左侧和右侧)会有一个图像,它应该显示上一个和下一个图像的某些部分。我为UICollectionView设置了框架是320 * 320。单元格大小为290 * 320。(单元格最小间距为10)1
以下两个链接描述了我的要求。提前谢谢。
(这就是我想要的)2
答案 0 :(得分:9)
您是否尝试将UICollectionViewFlowLayout的滚动方向设置为水平?
[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
您需要在集合视图上启用分页,如下所示:
[yourCollectionView setPagingEnabled:YES];
答案 1 :(得分:6)
我拿了shtefane's answer并改进了它。输入您自己的cellWidth
和cellPadding
值。
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
{
CGFloat cellWidth = self.cellWidth;
CGFloat cellPadding = 9;
NSInteger page = (scrollView.contentOffset.x - cellWidth / 2) / (cellWidth + cellPadding) + 1;
if (velocity.x > 0) page++;
if (velocity.x < 0) page--;
page = MAX(page,0);
CGFloat newOffset = page * (cellWidth + cellPadding);
targetContentOffset->x = newOffset;
}
答案 2 :(得分:3)
如果在collectionView中使用pagining,它将滚动一页而不是一个单元格。您可以禁用分页并实现ScrollViewDelegate
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
CGFloat pageW = 300;
int page = scrollView.contentOffset.x / pageW;
CGFloat newOffset =(page + ((velocity.x > 0)? 1 : -1)) * (pageW - 20);
CGPoint target = CGPointMake(newOffset, 0);
targetContentOffset = ⌖
NSLog(@"end Drag at %f /%i /%f",scrollView.contentOffset.x, page, velocity.x);
}
只有一个与标准分页不同:如果你快速拖动,Collection会滚动多个单元格。 别忘了添加UIScrollViewDelegate
答案 3 :(得分:1)
这是Rickster回复的一个有效的swift4版本:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let cellWidth = 174 as CGFloat
let cellPadding = 10 as CGFloat
var page = (scrollView.contentOffset.x - cellWidth / 2) / (cellWidth + cellPadding) + 1
if (velocity.x > 0) { page += 1 }
if (velocity.x < 0) { page -= 1 }
page = max(page,0)
targetContentOffset.pointee.x = page * (cellWidth + cellPadding)
}
答案 4 :(得分:0)
参考Rickster的答案,我用Swift 4重写:
/* paging */
extension AlbumViewController {
/* In case the user scrolls for a long swipe, the scroll view should animate to the nearest page when the scrollview decelerated. */
override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
scrollToPage(scrollView, withVelocity: CGPoint(x:0, y:0))
}
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
scrollToPage(scrollView, withVelocity: velocity)
}
func scrollToPage(_ scrollView: UIScrollView, withVelocity velocity: CGPoint) {
let cellWidth: CGFloat = cellSize
let cellPadding: CGFloat = 10
var page: Int = Int((scrollView.contentOffset.x - cellWidth / 2) / (cellWidth + cellPadding) + 1)
if velocity.x > 0 {
page += 1
}
if velocity.x < 0 {
page -= 1
}
page = max(page, 0)
let newOffset: CGFloat = CGFloat(page) * (cellWidth + cellPadding)
scrollView.setContentOffset(CGPoint(x:newOffset, y:0), animated: true)
}
}
答案 5 :(得分:0)
只需使用collectionView.isPagingEnabled = true;
答案 6 :(得分:0)
完整来源为here
这支持RTL(从右到左)
collectionView.decelerationRate = .fast
// paging
extension ViewController: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.dragStartPoint = scrollView.contentOffset
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let isRTL = UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft
let pageWidth = UIScreen.main.bounds.size.width - ViewController.left - ViewController.right + ViewController.lineSpacing
if scrollView.contentOffset.x == targetContentOffset.pointee.x { // no decelerate
if fabsf(Float(self.dragStartPoint.x - scrollView.contentOffset.x)) > 40 { // min move distance = 40
let dragLeft = self.dragStartPoint.x < scrollView.contentOffset.x
if dragLeft {
self.currentPage = isRTL ? self.currentPage - 1 : self.currentPage + 1
} else {
self.currentPage = isRTL ? self.currentPage + 1 : self.currentPage - 1
}
}
} else if scrollView.contentOffset.x > targetContentOffset.pointee.x {
let maxRight = scrollView.contentSize.width - UIScreen.main.bounds.size.width
if scrollView.contentOffset.x <= maxRight { // not right bounce
self.currentPage = isRTL ? self.currentPage + 1 : self.currentPage - 1
}
} else {
if scrollView.contentOffset.x >= 0 { // not left bounce
self.currentPage = isRTL ? self.currentPage - 1 : self.currentPage + 1
}
}
self.currentPage = max(0, self.currentPage)
self.currentPage = min(self.numberOfPages - 1, self.currentPage)
var offset = targetContentOffset.pointee
if isRTL {
offset.x = CGFloat(self.numberOfPages - self.currentPage - 1) * pageWidth
} else {
offset.x = CGFloat(self.currentPage) * pageWidth
}
targetContentOffset.pointee = offset
}
}