本文介绍了如何使UIScrollView捕获到图标(如App Store:功能)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我想获得的是与此滚动视图具有相同的行为: 我知道这是使用HTML而不是本机API,以实现它作为一个UIKit组件。 现在,我正在寻找的行为: 请注意,这是一个分页滚动视图,但页面大小小于视图的宽度。 当从右端向左滚动时,它会抓取到最右边的项目。 同一页面,但现在从右到左: 我试过: 我试图使滚动视图比它的超级视图和覆盖hitTest小, 我已经尝试实现scrollViewWillEndDragging:withVelocity:targetContentOffset:并设置targetContentOffset我想要的,但因为我不能改变速度,它只是滚动太慢或太快。 我尝试实现scrollViewDidEndDecelerating:然后动画到正确的偏移,但滚动视图先停止然后移动,它看起来不自然。 我已经尝试实现scrollViewDidEndDragging:willDecelerate:然后动画到正确的偏移,但滚动视图跳跃,并没有正确的动画。 我没有想法。 谢谢! 更新: 我最终使用Rob Mayoff的方法,看起来很干净。 我改变它,所以当速度为0时,例如当用户拖动,停止和释放手指时,它会工作。 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(CGPoint *)targetContentOffset { CGFloat maxOffset = scrollView.contentSize.width - scrollView.bounds.size.width; CGFloat minOffset = 0; if(velocity.x == 0){ CGFloat targetX = MAX(minOffset,MIN(maxOffset,targetContentOffset-> x)); CGFloat diff = targetX - baseOffset; if(ABS(diff)> offsetStep / 2){ if(diff> 0){ // left left baseOffset = MIN(maxOffset ,baseOffset + offsetStep); } else { // go right baseOffset = MAX(minOffset,baseOffset - offsetStep); } } } else { if(velocity.x> 0){ baseOffset = MIN(maxOffset,baseOffset + offsetStep); } else { baseOffset = MAX(minOffset,baseOffset - offsetStep); } } targetContentOffset-> x = baseOffset; } 此解决方案的唯一问题是, 反弹效应。感觉卡住。 解决方案设置 scrollView.decelerationRate = UIScrollViewDecelerationRateFast c $ c> scrollViewWillEndDragging:withVelocity:targetContentOffset:,似乎对我使用集合视图。 首先,变量: @implementation ViewController { NSString * cellClassName; CGFloat baseOffset; CGFloat offsetStep; } 在 viewDidLoad 我设置视图的 decelerationRate : - (void)viewDidLoad { [super viewDidLoad]; cellClassName = NSStringFromClass([MyCell class]); [self.collectionView registerNib:[UINib nibWithNibName:cellClassName bundle:nil] forCellWithReuseIdentifier:cellClassName]; self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast; } 我需要 offsetStep 是适合在视图的屏幕边界上的整数个项目的大小。我在 viewDidLayoutSubviews 中计算它: - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; UICollectionViewFlowLayout * layout =(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; CGFloat stepUnit = layout.itemSize.width + layout.minimumLineSpacing; offsetStep = stepUnit * floorf(self.collectionView.bounds.size.width / stepUnit); } 我需要 baseOffset 到滚动开始之前的视图的X偏移。我初始化它在 viewDidAppear:: - (void)viewDidAppear: (BOOL)animated { [super viewDidAppear:animated]; baseOffset = self.collectionView.contentOffset.x; } 然后我需要强制视图滚动 offsetStep 。我在 scrollViewWillEndDragging:withVelocity:targetContentOffset:。根据速度,我通过 offsetStep baseOffset >。但我将 baseOffset 钳制到最小值0和最大值 contentSize.width - bounds.size.width 。 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { if(velocity.x< 0){ baseOffset = MAX(0,baseOffset - offsetStep); } else if(velocity.x> 0){ baseOffset = MIN(scrollView.contentSize.width - scrollView.bounds.size.width,baseOffset + offsetStep); } targetContentOffset-> x = baseOffset;请注意,我不在乎什么 targetContentOffset- } $ b 。 这样会对齐到最左边的可见项目的左边缘,直到用户滚动到最后一个项目的方式。此时,它与最右边的可见项目的右边缘对齐,直到用户向左滚动。这似乎与App Store应用程序的行为匹配。 如果这不适合你,你可以尝试替换最后一行( targetContentOffset-> x = baseOffset )与此: dispatch_async(dispatch_get_main_queue [scrollView setContentOffset:CGPointMake(baseOffset,0)animated:YES]; }); 这也适用于我。 您可以在此git存储库中找到我的测试应用。 What I want to get is the same behaviour that this scroll view has:I know that this is using HTML and not the native API, but I'm trying to implement it as a UIKit component.Now, to the behaviour I'm looking for:Notice that it's a paged scroll view, but the "page size" is less than the view's width.When you scroll it from left to right each page "snap" to the left-most item.When you scroll it from the right end to the left it "snaps" to the right-most item.The same page but now right-to-left:What I've tried:I've tried making the scroll view smaller than it's super view and overriding hitTest, and that got me that left-to-right behaviour.I've tried implementing scrollViewWillEndDragging:withVelocity:targetContentOffset: and setting the targetContentOffset I want but since I can't change the velocity it just scrolls too slowly or too fast.I've tried implementing scrollViewDidEndDecelerating: and then animating to the correct offset but the scroll view first stops then moves, it doesn't look natural. I've tried implementing scrollViewDidEndDragging:willDecelerate: and then animating to the correct offset but the scroll view "jumps" and does not animate correctly.I'm out of ideas.Thanks!Update:I ended up using Rob Mayoff's method, it looks clean. I changed it so it would work when the velocity is 0, for example when a user drags, stops and releases the finger.- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(CGPoint *)targetContentOffset { CGFloat maxOffset = scrollView.contentSize.width - scrollView.bounds.size.width; CGFloat minOffset = 0; if (velocity.x == 0) { CGFloat targetX = MAX(minOffset,MIN(maxOffset, targetContentOffset->x)); CGFloat diff = targetX - baseOffset; if (ABS(diff) > offsetStep/2) { if (diff > 0) { //going left baseOffset = MIN(maxOffset, baseOffset + offsetStep); } else { //going right baseOffset = MAX(minOffset, baseOffset - offsetStep); } } } else { if (velocity.x > 0) { baseOffset = MIN(maxOffset, baseOffset + offsetStep); } else { baseOffset = MAX(minOffset, baseOffset - offsetStep); } } targetContentOffset->x = baseOffset;}The only problem with this solution is that swiping the scroll view doesn't produce the "bounce" effect. It feels "stuck". 解决方案 Setting scrollView.decelerationRate = UIScrollViewDecelerationRateFast, combined with implementing scrollViewWillEndDragging:withVelocity:targetContentOffset:, seems to work for me using a collection view.First, I give myself some instance variables:@implementation ViewController { NSString *cellClassName; CGFloat baseOffset; CGFloat offsetStep;}In viewDidLoad, I set the view's decelerationRate:- (void)viewDidLoad { [super viewDidLoad]; cellClassName = NSStringFromClass([MyCell class]); [self.collectionView registerNib:[UINib nibWithNibName:cellClassName bundle:nil] forCellWithReuseIdentifier:cellClassName]; self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast;}I need offsetStep to be the size of an integral number of items that fit in the view's on-screen bounds. I compute it in viewDidLayoutSubviews:- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; CGFloat stepUnit = layout.itemSize.width + layout.minimumLineSpacing; offsetStep = stepUnit * floorf(self.collectionView.bounds.size.width / stepUnit);}I need baseOffset to the be the X offset of the view before scrolling starts. I initialize it in viewDidAppear::- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; baseOffset = self.collectionView.contentOffset.x;}Then I need to force the view to scroll in steps of offsetStep. I do that in scrollViewWillEndDragging:withVelocity:targetContentOffset:. Depending on the velocity, I increase or decrease baseOffset by offsetStep. But I clamp baseOffset to a minimum of 0 and a maximum of the contentSize.width - bounds.size.width.- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { if (velocity.x < 0) { baseOffset = MAX(0, baseOffset - offsetStep); } else if (velocity.x > 0) { baseOffset = MIN(scrollView.contentSize.width - scrollView.bounds.size.width, baseOffset + offsetStep); } targetContentOffset->x = baseOffset;}Note that I don't care what targetContentOffset->x comes in as.This has the effect of aligning to the left edge of the leftmost visible item, until the user scrolls all the way to the last item. At that point it aligns to the right edge of the rightmost visible item, until the user scroll all the way to the left. This seems to match the behavior of the App Store app.If that doesn't work for you, you can try replacing the last line (targetContentOffset->x = baseOffset) with this: dispatch_async(dispatch_get_main_queue(), ^{ [scrollView setContentOffset:CGPointMake(baseOffset, 0) animated:YES]; });That also works for me.You can find my test app in this git repository. 这篇关于如何使UIScrollView捕获到图标(如App Store:功能)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 09-20 23:35