大道之行,天下为公。这篇文章主要讲述如何使用autolayout将UIScrollView滚动到viewWillAppear的底部,没有可视化动画相关的知识,希望能为你提供帮助。
这是问题所在:
【如何使用autolayout将UIScrollView滚动到viewWillAppear的底部,没有可视化动画】我在UIScrollView中放了一堆视图。这些子视图的大小和位置由约束定义。这非常有效,滚动效果也很好。到现在为止还挺好。
但是,当我第一次在屏幕上显示viewcontroller时,我希望我的scrollview一直滚动到底部,这就是麻烦开始的地方。为了知道底部的位置,我需要知道子视图中最低元素的位置和大小。也应该很容易(因为我在某处提到了UIView):得到UIView的框架并且瞧。
我想在滚动视图出现在屏幕上之前将其滚动到底部(基本上,在viewWillAppear :)中,但是仅在viewWillAppear之后和viewDidAppear:之前调用约束。
在viewWillAppear中获取UIView框架给了我一个零大小的CGRect。在viewDidAppear中做同样的事情给了我正确的CGRect。但是viewDidAppear对我来说太迟了,因为滚动视图已经在屏幕上,所以你看到内容向上移动。
有没有人有这个很好的解决方案?我尝试将代码放在viewDidLayoutSubviews中,但这也不起作用。
答案viewWillAppear
的问题在于它在布局发生之前被调用。您必须在布局后调整滚动视图的内容偏移量 - 使用viewDidLayoutSubviews
方法。在这是我的解决方案:
@property (nonatomic, assign) BOOL shouldScrollToBottom;
- (void)viewDidLoad
{
[super viewDidLoad];
_shouldScrollToBottom = YES;
}- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Scroll table view to the last row
if (_shouldScrollToBottom)
{
_shouldScrollToBottom = NO;
[_scrollView setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
}
}
另一答案这就是我所做的,它适用于我(通过自动布局计算的单元格高度):
class MessagesTableViewController: UITableViewController
{
var shouldScrollToBottom = falseoverride func viewDidLoad()
{
super.viewDidLoad()
...
shouldScrollToBottom = true
}override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if(shouldScrollToBottom == true)
{
shouldScrollToBottom = false
goToBottom()
}
}private func goToBottom()
{
if(data.count == 0)
{
return
}
let indexPath = NSIndexPath(forRow: tableView.numberOfRowsInSection(0)-1, inSection: 0)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false)
}
}
另一答案我也遇到了这个问题!在
viewDidAppear()
之前,视图没有滚动到所需的页面。 viewDidLayoutSubviews()
有多个子视图,所以在这个函数中做一次,like Thomas suggested,对我来说也不起作用。但是,如果你使用一个小技巧,viewDidLayoutSubviews()
方法是有效的:每次在创建视图期间调用
viewDidLayoutSubviews()
时,您都需要尝试滚动到所需的点。然后,在显示视图后,您不再希望再调用它。因此,在初始布局之后添加在viewDidAppear()
中更改的控制变量。这是完整的例子:var needsFirstScroll = trueoverride func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()if(needsFirstScroll) {
var frame = CGRect() // placeholder, do your frame calculation here
scrollView.scrollRectToVisible(frame, animated: false)
}
}override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
needsFirstScroll = false
}
另一答案我最终提出的解决方案是:
- 将scrollview的所有子视图存储在1个contentview中,而不是直接作为scrollview的子视图
- 观察内容视图的界限何时发生变化
- 每次他们改变时都会将
scrollRectToVisible
放到scrollview的底部 - 检测到
scrollViewWillBeginDragging
委托调用后立即禁用自动滚动到底部,以便在用户开始移动滚动视图时停止自动滚动
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.tableView.numberOfRowsInSection:0] inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
}
推荐阅读
- 从Android Things设备上的应用程序中选择WiFi网络(Raspberry Pi 3)
- “离子cordova运行android”无法使用cordova-android@7.0.0
- 如何使用Android中的Camera.Parameter在黑白模式下打开和捕捉相机图片
- win10怎样设置宽带连接,本文教您修好宽带连接问
- windows10 cmd|本文教您windows10系统下cmd命令大全
- Win10怎样退回Win 8,本文教您怎样退回
- 电脑快捷键运用大全,本文教您只需看这篇就够了
- win10无法进入安全模式怎样办,本文教您处理的方
- windows10及安装最新推荐