ios 使用 scrollViewWillEndDragging 自定义 UIScrollView 分页
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9367600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom UIScrollView paging with scrollViewWillEndDragging
提问by Alex
I'm trying to use the new scrollViewWillEndDragging:withVelocity:targetContentOffset: UIScrollView delegate call in iOS 5 but i can't seem to get it to actually respond to me correctly. I'm changing the targetContentOffset->x value but it never ends up being used. I know the code is being ran because it'll hit breakpoints in that function. I've even tried setting the offset value to a hard coded number so i'd know where it would end up but it never works.
我正在尝试在 iOS 5 中使用新的 scrollViewWillEndDragging:withVelocity:targetContentOffset: UIScrollView 委托调用,但我似乎无法让它真正正确地响应我。我正在更改 targetContentOffset->x 值,但它永远不会被使用。我知道代码正在运行,因为它会在该函数中遇到断点。我什至尝试将偏移值设置为硬编码数字,这样我就知道它会在哪里结束,但它永远不会起作用。
Has anyone been able to use this correctly and make it work? Is there any other delegate call that must be implemented in order for this to work?
有没有人能够正确使用它并使其工作?是否有任何其他委托调用必须实现才能使其工作?
Here's my code in case someone sees something wrong with it:
这是我的代码,以防有人发现它有问题:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
// goodOffsetX returns the contentOffset i want the scrollView to stop at
CGFloat goodOffsetX = [self _horizontalContentOffsetForTargetHorizontalContentOffset:(*targetContentOffset).x velocity:velocity.x];
NSLog( @" " );
NSLog( @"scrollViewWillEndDragging" );
NSLog( @" velocity: %f", velocity.x );
NSLog( @" currentX: %f", scrollView.contentOffset.x );
NSLog( @" uikit targetX: %f", (*targetContentOffset).x );
NSLog( @" pagedX: %f", goodOffsetX );
targetContentOffset->x = goodOffsetX;
}
回答by m8labs
You can implement custom paging with this code:
您可以使用以下代码实现自定义分页:
- (float) pageWidth {
return ((UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout).itemSize.width +
((UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout).minimumInteritemSpacing;
}
- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView {
CGFloat pageWidth = self.collectionView.frame.size.width + 10 /* Optional Photo app like gap between images. Or use [self pageWidth] in case if you want the next page be also visible */;
_currentPage = floor((self.collectionView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
NSLog(@"Dragging - You are now on page %i", _currentPage);
}
- (void) scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint*)targetContentOffset {
CGFloat pageWidth = self.collectionView.frame.size.width + 10; // [self pageWidth]
int newPage = _currentPage;
if (velocity.x == 0) { // slow dragging not lifting finger
newPage = floor((targetContentOffset->x - pageWidth / 2) / pageWidth) + 1;
}
else {
newPage = velocity.x > 0 ? _currentPage + 1 : _currentPage - 1;
if (newPage < 0)
newPage = 0;
if (newPage > self.collectionView.contentSize.width / pageWidth)
newPage = ceil(self.collectionView.contentSize.width / pageWidth) - 1.0;
}
NSLog(@"Dragging - You will be on %i page (from page %i)", newPage, _currentPage);
*targetContentOffset = CGPointMake(newPage * pageWidth, targetContentOffset->y);
}
Of course you must set pagingEnabled = NO. _currentPage is a class iVar. Thanks to http://www.mysamplecode.com/2012/12/ios-scrollview-example-with-paging.htmlfor pointing the right way.
当然你必须设置 pagingEnabled = NO。_currentPage 是一个类 iVar。感谢http://www.mysamplecode.com/2012/12/ios-scrollview-example-with-paging.html指出正确的方法。
回答by Damien Romito
SWIFT 3
斯威夫特 3
With a demo here https://github.com/damienromito/CollectionViewCustom
这里有一个演示https://github.com/damienromito/CollectionViewCustom
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let pageWidth = Float(itemWidth + itemSpacing)
let targetXContentOffset = Float(targetContentOffset.pointee.x)
let contentWidth = Float(collectionView!.contentSize.width )
var newPage = Float(self.pageControl.currentPage)
if velocity.x == 0 {
newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0
} else {
newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)
if newPage < 0 {
newPage = 0
}
if (newPage > contentWidth / pageWidth) {
newPage = ceil(contentWidth / pageWidth) - 1.0
}
}
let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)
targetContentOffset.pointee = point
}
回答by heckman
I was able to run a quick test and got this to correctly fire and make my object stop as desired. I did this using the following simple test:
我能够运行一个快速测试并使其正确触发并使我的对象根据需要停止。我使用以下简单测试做到了这一点:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
targetContentOffset->x = scrollView.contentOffset.x - 10;
}
It seems that this method is likely not the issue in your code, but it is more likely that your 'goodOffsetX' is not correctly calculating a valid value to stop at.
似乎此方法可能不是您代码中的问题,但更有可能是您的“goodOffsetX”没有正确计算要停止的有效值。
回答by Glauco Neves
Swift 2.2:
斯威夫特 2.2:
extension SomeCollectionViewController {
override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
let pageWidth = Float(collectionView!.frame.size.width)
let xCurrentOffset = Float(collectionView!.contentOffset.x)
currentPage = floor((xCurrentOffset - pageWidth / 2) / pageWidth) + 1
}
override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let pageWidth = Float(collectionView!.frame.size.width)
let targetXContentOffset = Float(targetContentOffset.memory.x)
let contentWidth = Float(collectionView!.contentSize.width)
var newPage = currentPage
if velocity.x == 0 {
newPage = floor((targetXContentOffset - pageWidth / 2) / pageWidth) + 1
} else {
newPage = velocity.x > 0 ? currentPage + 1 : currentPage - 1
if newPage < 0 {
newPage = 0
}
if newPage > contentWidth / pageWidth {
newPage = ceil(contentWidth / pageWidth) - 1.0
}
}
targetContentOffset.memory.x = CGFloat(newPage * pageWidth)
}
}
I also used the collectionView?.decelerationRate = UIScrollViewDecelerationRateFast
as suggested by @skagedal to improve page speed.
我还使用了collectionView?.decelerationRate = UIScrollViewDecelerationRateFast
@skagedal 的建议来提高页面速度。
回答by buoge
public func scrollViewWillEndDragging(_ scrollView: UIScrollView ,withVelocity velocity: CGPoint, targetContentOffset:
UnsafeMutablePointer<CGPoint>){
let pageWidth = Float(appWidth + itemSpacing)
let targetXContentOffset = Float(targetContentOffset.pointee.x)
var newPage = Float(currentPageIndex)
// I use this way calculate newPage:
newPage = roundf(targetXContentOffset / pageWidth);
//if velocity.x == 0 {
// newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0
//} else {
// newPage = Float(velocity.x > 0 ? newPage + 1 : newPage - 1)
// if newPage < 0 {
// newPage = 0
// }
// if (newPage > contentWidth / pageWidth) {
// newPage = ceil(contentWidth / pageWidth) - 1.0
// }
//}
let targetOffsetX = CGFloat(newPage * pageWidth)
let point = CGPoint (x: targetOffsetX, y: targetContentOffset.pointee.y)
targetContentOffset.pointee = point
}