Nip*_*rus 7 cocoa-touch uiscrollview ios
该UIScrollView中有很多提供给程序员的信息,但我没有看到一个明显的方法来控制位置,控制停止从滚动手势减速后.
基本上我希望scrollview能够捕捉到屏幕的特定区域.用户仍然可以像平常一样滚动,但是当他们停止滚动时,视图应该捕捉到最相关的位置,并且在轻弹手势的情况下,减速也应该停在这些位置.
有没有一种简单的方法来做这样的事情,或者我应该考虑实现这种效果的唯一方法来编写自定义滚动控件?
idS*_*tar 27
由于UITableView是UIScrollView子类,因此您可以实现UIScrollViewDelegate方法:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
Run Code Online (Sandbox Code Playgroud)
然后计算所需的最接近的目标内容偏移量,并在inout CGPoint参数中设置该偏移量.
我刚试过这个,效果很好.
首先,检索非制导偏移,如下所示:
CGFloat unguidedOffsetY = targetContentOffset->y;
Run Code Online (Sandbox Code Playgroud)
然后通过一些数学计算,你想要它,注意表头的高度.以下是我的代码中处理代表美国各州的自定义单元格的示例:
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;
Run Code Online (Sandbox Code Playgroud)
上面的最后一行实际上将值写回到inout参数中,该参数告诉滚动视图这是你想要捕捉的y偏移量.
最后,如果你正在处理一个获取的结果控制器,并且你想知道刚捕到的是什么,你可以做这样的事情(在我的例子中,属性"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;
Run Code Online (Sandbox Code Playgroud)
OFF-TOPIC注意:正如您可能猜到的那样,"log4Debug"语句只是记录.顺便说一句,我正在使用Lumberjack,但我更喜欢旧Log4Cocoa的命令语法.
在scrollViewDidEndDecelerating:
和之后scrollViewDidEndDragging:willDecelerate:
(最后一个当减速参数为NO
)时,你应该将你的contentOffset
参数设置UIScrollView
到所需的位置.
您还可以通过检查contentOffset
滚动视图的属性来了解当前位置,然后计算最接近的所需区域
虽然您不必创建自己的滚动控件,但您必须手动滚动到所需的位置
小智 7
要添加到felipe所说的内容,我最近创建了一个表格视图,它以与UIPicker类似的方式捕捉到单元格.一个聪明的scrollview委托绝对是这样做的方式(你也可以在uitableview上做到这一点,因为它只是uiscrollview的一个子类).
一旦滚动视图开始减速(即在调用scrollViewDidEndDragging:willDecelerate:之后),响应scrollViewDidScroll:并使用前一个scroll事件计算diff,我完成了这个.
当diff小于2到5个像素时,我检查最近的单元格,然后等待该单元格已经过几个像素,然后使用setContentOffset向后滚动另一个方向:animated:.这会产生一点反弹效果,非常适合用户体验,因为它可以对捕捉提供良好的反馈.
当桌子在顶部或底部弹跳时,你必须聪明而不做任何事情(将偏移量与0比较或者内容大小会告诉你).在我的情况下,它工作得很好,因为单元格很小(大约80-100px高),如果你有一个具有更大内容区域的常规滚动视图,你可能会遇到问题.当然,你不会总是减速经过一个单元格,所以在这种情况下我只是滚动到最近的单元格,动画看起来很生涩.事实证明,正确的调整,它几乎没有发生过,所以我对此很酷.花几个小时调整实际值取决于您的特定屏幕,你可以得到一些体面的东西.
我也尝试了天真的方法,调用setContentOffset:animated:on scrollViewDidEndDecelerating:但是它创建了一个非常奇怪的动画(或者如果你没有动画,只是简单的混乱跳跃),越慢,减速率就越低(你'我会从慢动作跳到更快的动作.
所以回答这个问题: - 不,没有简单的方法可以做到这一点,它需要一些时间来抛光以前算法的实际值,这可能在你的屏幕上根本不起作用, - 不要试图创建你自己的滚动视图,你只是浪费时间,并严重重新发明一堆美丽的工程苹果与卡车装载的bug.scrollview委托是您的问题的关键.
尝试这样的事情:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
这利用了int的十进制后数字的下降.还假设您的所有视图都从0,0开始排列,只有contentOffset才能显示在不同的区域.
注意:挂起代理,这非常正常.你得到一个修改版本 - 我只有实际的常量大声笑.我重命名了变量,因此您可以轻松阅读
归档时间: |
|
查看次数: |
10405 次 |
最近记录: |