UIScrollView有很多信息可供程序员使用,但我没有看到明显的方式来控制从滚动手势减速后控件停止的位置。UIScrollView - 捕捉减速时的控制
基本上我想滚动视图捕捉到屏幕的特定区域。用户仍然可以像正常一样滚动,但是当它们停止滚动时,视图应该捕捉到最相关的位置,并且在轻弹手势的情况下,减速也应该在这些位置处停止。
有没有简单的方法来做这样的事情,或者我应该考虑完成这种效果来编写自定义滚动控件的唯一方法?
UIScrollView有很多信息可供程序员使用,但我没有看到明显的方式来控制从滚动手势减速后控件停止的位置。UIScrollView - 捕捉减速时的控制
基本上我想滚动视图捕捉到屏幕的特定区域。用户仍然可以像正常一样滚动,但是当它们停止滚动时,视图应该捕捉到最相关的位置,并且在轻弹手势的情况下,减速也应该在这些位置处停止。
有没有简单的方法来做这样的事情,或者我应该考虑完成这种效果来编写自定义滚动控件的唯一方法?
的scrollViewDidEndDecelerating:
和scrollViewDidEndDragging:willDecelerate:
(最后一个正当的减速参数是NO
)后,你应该设置你的UIScrollView
到所需位置的contentOffset
参数。
你也知道通过检查你的滚动型的contentOffset
属性的当前位置,然后计算出你有
虽然你不必创建自己的滚动控制最接近期望的区域,你将有手动滚动到所需的位置
要添加到felipe说,我最近创建了一个表格视图,以UIPicker类似的方式捕捉单元格。 一个聪明的scrollview委托绝对是这样做的(你也可以在uitableview上做到这一点,因为它只是uiscrollview的子类)。
我这个做的,一旦滚动视图开始减速(即scrollViewDidEndDragging后:willDecelerate:叫),响应scrollViewDidScroll:和计算与先前的滚动事件的差异。
当diff小于2至5个像素时,我检查最近的单元格,然后等待该单元格已经过了几个像素,然后用setContentOffset向另一个方向滚动:animated: 。 这会创建一个对用户体验非常好的小反弹效果,因为它可以为拍摄提供良好的反馈。
当表格在顶部或底部弹跳时(将偏移量与0进行比较或内容大小会告诉您这一点),您必须非常聪明,不要做任何事情。 在我的情况下它工作得很好,因为单元格很小(大约80-100px),如果您有一个具有较大内容区域的常规滚动视图,则可能会遇到问题。 当然,你不会总是减速通过一个单元格,所以在这种情况下,我只是滚动到最近的单元格,动画看起来很生涩。发现正确的调整,它几乎没有发生,所以我很酷。 花几个小时根据具体的屏幕调整实际值,你可以得到一些体面的。
我也试过天真的态度,要求setContentOffset:动画:在scrollViewDidEndDecelerating:但它创建了一个很奇怪的动画(或者只是普通的混乱跳,如果你不动画),变得更糟减速率越低是(你会从缓慢的运动跳到更快的运动)。
因此,要回答这个问题: - 不,有没有简单的方法来做到这一点,它会需要一些时间打磨以前的算法,这可能不是你的屏幕, 不惜一切工作的实际值 - 不要试图创建自己的滚动视图,你只需要浪费时间并重新创建一个由卡车装载的bug创建的漂亮工程苹果。 scrollview委托是你的问题的关键。
由于UITableView的是一个UIScrollView子类,你可以实现的UIScrollViewDelegate方法:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
,然后计算一下最接近期望的目标内容偏移是你想要的,并设置在INOUT CGPoint参数。
我刚刚试过这个,它运作良好。
首先,检索制导这样的偏移:
CGFloat unguidedOffsetY = targetContentOffset->y;
然后通过一些数学,在那里你会希望它是弄清楚,注意表头的高度。下面是我的代码处理代表美国各州自细胞样本:
CGFloat guidedOffsetY;
if (unguidedOffsetY > kFirstStateTableViewOffsetHeight) {
int remainder = lroundf(unguidedOffsetY) % lroundf(kStateTableCell_Height_Unrotated);
log4Debug(@"Remainder: %d", remainder);
if (remainder < (kStateTableCell_Height_Unrotated/2)) {
guidedOffsetY = unguidedOffsetY - remainder;
}
else {
guidedOffsetY = unguidedOffsetY - remainder + kStateTableCell_Height_Unrotated;
}
}
else {
guidedOffsetY = 0;
}
targetContentOffset->y = guidedOffsetY;
上面的最后一行,实际写入值回INOUT参数,它告诉滚动认为,这是y偏移你” d喜欢它捕捉。最后,如果你正在处理一个抓取的结果控制器,并且你想知道刚刚捕捉到的结果,你可以做这样的事情(在我的例子中,属性“states”是美国国家的FRC )。我使用该信息来设置按钮标题:
NSUInteger selectedStateIndexPosition = floorf((guidedOffsetY + kFirstStateTableViewOffsetHeight)/kStateTableCell_Height_Unrotated);
log4Debug(@"selectedStateIndexPosition: %d", selectedStateIndexPosition);
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:selectedStateIndexPosition inSection:0];
CCState *selectedState = [self.states objectAtIndexPath:indexPath];
log4Debug(@"Selected State: %@", selectedState.name);
self.stateSelectionButton.titleLabel.text = selectedState.name;
题外话注:正如你可能猜到了,“log4Debug”语句只是记录。顺便说一下,我为此使用了Lumberjack,但我更喜欢旧Log4Cocoa中的命令语法。
谢谢!超级有用。 – theVurt 2012-07-09 12:30:49
推动可滚动视图控制器时,contentOffset将考虑UINavigationBar高度和原点。 (不知道为什么它这样做,因为这是没有道理的,但它就是这样) – cynistersix 2014-05-30 00:02:45
尝试这样:
- (void) snapScroll;
{
int temp = (theScrollView.contentOffset.x+halfOfASubviewsWidth)/widthOfSubview;
theScrollView.contentOffset = CGPointMake(temp*widthOfSubview , 0);
}
- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
if (!decelerate) {
[self snapScroll];
}
}
- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self snapScroll];
}
这需要的小数点后的位数INT的下降的优势。同样假设你的所有视图都是从0,0排列起来的,只有contentOffset是它在不同区域显示的内容。
注意:挂钩委托,这工作得很好。你得到一个修改版本 - 我的实际常量大声笑。我重命名了变量,以便您可以轻松读取它
谢谢@kra,这绝对会创建一个更流畅的动画,并且scrollview感觉更自然! – 2014-02-15 21:07:08