方式一 (实现scrollView的代理较为通用)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
self.start = scrollView.contentOffset.x;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
self.end = scrollView.contentOffset.x;
NSInteger index = self.currentSelectedIndex;
if (self.end - self.start >= 20) {
index++;
} else if (self.start - self.end >= 20) {
index--;
}
if (index < 0) {
index = 0;
}
if (index >= self.dataSource.count) {
index = self.dataSource.count - 1;
}
self.currentSelectedIndex = index;
dispatch_async(dispatch_get_main_queue(), ^{
[self.centerCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
});
}
方式二 (自定义UICollectionViewFlowLayout)
class TestLayout: UICollectionViewFlowLayout {
var stepSpace:CGFloat {
return self.itemSize.width + self.minimumLineSpacing
}
var lastPosition:CGPoint = .zero
override func prepare() {
super.prepare()
self.collectionView?.decelerationRate = .fast
}
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
let move = CGFloat(abs(Int32(self.lastPosition.x - proposedContentOffset.x)))
let factor = move / self.stepSpace > 1
let trigger = !(-0.3...0.3).contains(Double(velocity.x))
var offset = proposedContentOffset
switch velocity.x {
// 左滑
case let x where x > 0 && trigger && !factor:
offset.x = stepSpace * CGFloat(ceil(Double(proposedContentOffset.x / stepSpace)))
case let x where x > 0 && trigger && factor:
offset.x = lastPosition.x + stepSpace
// 右滑
case let x where x < 0 && trigger && !factor:
offset.x = stepSpace * CGFloat(floor(Double(proposedContentOffset.x / stepSpace)))
case let x where x < 0 && trigger && factor:
offset.x = lastPosition.x - stepSpace
default:
offset = lastPosition
break
}
lastPosition = offset
return offset
}
}
第三种 修改layout的_setInterpageSpacing的值
OC
if ([self.collectionView respondsToSelector:NSSelectorFromString(@"_setInterpageSpacing:")]) {
((void(*)(id,SEL,CGSize))objc_msgSend)(self.collectionView,NSSelectorFromString(@"_setInterpageSpacing:"),CGSizeMake(-(self.hzj_short), 0));
}
extension UICollectionViewFlowLayout {
private static var _hzj_short = "_hzj_short"
/**
*相对于collectionView的尺寸,在滑动方向减少的距离
*比如collectionView的尺寸(200,300),水平滑动,若想滑动160后边停止,则设置hzj_short=(200-160)=40
*/
var hzj_short:CGFloat? {
set{
objc_setAssociatedObject(self, &UICollectionViewFlowLayout._hzj_short, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get{
return objc_getAssociatedObject(self, &UICollectionViewFlowLayout._hzj_short) as? CGFloat
}
}
open override func prepare() {
super.prepare()
if let short = self.hzj_short {
self.collectionView?.decelerationRate = .fast
//使用kvc
if ((self.collectionView?.value(forKey: "interpageSpacing") as? CGSize) != nil) {
let size = self.scrollDirection == .horizontal ? CGSize(width: -short,height: 0) : CGSize(width: 0 ,height: -short)
self.collectionView?.setValue(size, forKey: "interpageSpacing")
}
if ((self.collectionView?.value(forKey: "pagingOrigin") as? CGPoint) != nil) {
self.collectionView?.setValue(CGPoint.zero, forKey: "pagingOrigin")
}
}
}
}
参考资料
https://www.jianshu.com/p/7093c04b90fe
网友评论