我试图复制iOS应用 Rdio 中显示的屏幕的大小调整行为。有问题的屏幕提供了所选专辑的概述,上半部分包含UIView,下半部分包含UITableView。当滚动tableView时,它首先向上调整大小以填充屏幕,然后在达到最大高度时开始正常滚动其内容。
经过一番搜索,我发现了这个问题:Dragging UITableView基本上要求同样的事情,然而其接受的方法与我最初的想法相同。试用,即使用UIPanGestureRecognizer并根据平移的平移调整tableviews高度。
不提供我正在寻找的行为。使用此方法只允许您静态地向上或向下拖动tableviews高度,并且它增加了panGesture覆盖tableViews的问题,然后阻止滚动内容。
Rdio应用程序的大小调整行为功能和感觉完全就像UIScrollView一样,它具有惯性。您可以将其完全拖动,向上或向下轻拂,然后平滑地调整大小。当tableView达到其全尺寸或原始半尺寸时,剩余的惯性似乎在tableview上传递,导致单元格像往常一样滚动该数量。我知道他们必须操纵UIScrollViews,我无法弄清楚如何。
作为最后一点,最终我将在这个屏幕上使用AutoLayout,所以我想知道这将如何可能阻碍或帮助这种情况。
更新
这种方法让我最接近我到目前为止所寻找的行为。 向上轻拂tableView的行为与我想要的完全相同(调整惯性并在达到最大高度时继续滚动),尽管灵敏度低于我想要的。然而,向下轻拂,没有惯性,立即停止。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect scrollViewFrame = scrollView.frame;
CGFloat scrollViewYOffset = scrollView.contentOffset.y;
if (scrollViewFrame.origin.y <= kTableViewMaxYOrigin || scrollViewFrame.origin.y <= _originalTableViewFrame.origin.y)
{
scrollViewFrame.origin.y -= scrollViewYOffset;
if(scrollViewFrame.origin.y >= kTableViewMaxYOrigin && scrollViewFrame.origin.y <= _originalTableViewFrame.origin.y)
{
scrollViewFrame.size.height += scrollViewYOffset;
scrollView.frame = scrollViewFrame;
scrollView.contentOffset = CGPointZero;
}
}
}
答案 0 :(得分:5)
我制作了一个使用autolayout的版本。 我花了一段时间的试验和错误才能使这一次正确!
请使用评论并询问我答案是否不清楚。
在viewDidLoad
中保存布局约束的初始高度,确定您希望滚动视图的最低值。
- (void)viewDidLoad
{
...
_initialTopLayoutConstraintHeight = self.topLayoutConstraint.constant;
...
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
BOOL leaveScrollAlone = self.topLayoutConstraint.constant == _initialTopLayoutConstraintHeight && scrollView.contentOffset.y <= 0;
if (leaveScrollAlone)
{
// This allows for bounce when swiping your finger downwards and reaching the stopping point
return;
}
// Do some capping of that layout constraint to keep it from going past the range you want it to be.
// In this case, I use self.topLayoutGuide.length so that my UICollectionView scales all the way until
// it hits the bottom of the navigation bar
CGFloat topLayoutConstraintLength = _initialTopLayoutConstraintHeight - scrollView.contentInset.top;
topLayoutConstraintLength = MAX(topLayoutConstraintLength, self.topLayoutGuide.length);
topLayoutConstraintLength = MIN(topLayoutConstraintLength, _initialTopLayoutConstraintHeight);
self.topLayoutConstraint.constant = topLayoutConstraintLength;
// Keep content seemingly still while the UICollectionView resizes
if (topLayoutConstraintLength > self.topLayoutGuide.length)
{
scrollView.contentInset = UIEdgeInsetsMake(scrollView.contentInset.top + scrollView.contentOffset.y,
scrollView.contentInset.left,
scrollView.contentInset.bottom,
scrollView.contentInset.right);
scrollView.contentOffset = CGPointZero;
}
// This helps get rid of the extraneous contentInset.top we accumulated for keeping
// the content static while the UICollectionView resizes
if (scrollView.contentOffset.y < 0)
{
self.topLayoutConstraint.constant -= scrollView.contentOffset.y;
scrollView.contentInset = UIEdgeInsetsMake(scrollView.contentInset.top + scrollView.contentOffset.y,
scrollView.contentInset.left,
scrollView.contentInset.bottom,
scrollView.contentInset.right);
}
// Prevents strange jittery artifacts
[self.view layoutIfNeeded];
}
答案 1 :(得分:3)
事实证明,在两个方向上进行平滑惯性调整的关键组件是通过其contentOffset.y更新scrollViews contentInset.top。
我相信回想起来这是有道理的,好像内部的内容已经在顶部,它不能再滚动,因此突然停止而不是平滑滚动。至少这是我的理解。
另一个关键点是确保单元格仅在达到最大或原始高度时才开始滚动。只需在每次调整视图大小时将scrollViews contentOffset设置为CGPointZero,直到达到最大或原始高度,即可完成此操作。
以下是展示如何实现此效果的- (void)scrollViewDidScroll:(UIScrollView *)scrollView
方法。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect scrollViewFrame = scrollView.frame;
CGFloat scrollViewTopContentInset = scrollView.contentInset.top;
CGFloat scrollViewYOffset = scrollView.contentOffset.y;
if (scrollViewFrame.origin.y <= kTableViewMaxYOrigin || scrollViewFrame.origin.y <= _originalTableViewFrame.origin.y)
{
scrollViewFrame.origin.y -= scrollViewYOffset;
if(scrollViewFrame.origin.y >= kTableViewMaxYOrigin && scrollViewFrame.origin.y <= _originalTableViewFrame.origin.y)
{
scrollViewFrame.size.height += scrollViewYOffset;
scrollViewTopContentInset += scrollViewYOffset;
scrollView.frame = scrollViewFrame;
scrollView.contentInset = UIEdgeInsetsMake(scrollViewTopContentInset, 0, 0, 0);
scrollView.contentOffset = CGPointZero;
}
}
}
答案 2 :(得分:0)
我没有看到有问题的应用,但是根据您的说明...在tableView
的委托方法-scrollViewDidScroll:
中,将tableView.frame.origin.y
设置为albumView.frame.height - tableView.contentOffset.y
并且相应地改变它的高度。
(如果你正在使用autolayout,你将不得不改变与tableView的框架有关的约束而不是框架本身。)