今天做一个页面,有大量的文字展示,需要用到UITextView。因为文字过多,自然有一部分无法显示,需要滑动后才能看到。不过当我把页面写完后,出来的效果是这样的。
默认的效果是,textview自动滑倒最底下。这肯定不符合我们的设想,我们希望的是一进来就从第一行显示。第一个想到的方法是进入页面后回滚会滚到首行。不过这个方法明显多此一举,心想textview应该有控制默认滚动到属性,结果还真被我找到了,不过这个属性藏的很深。
textview.layoutManager.allowsNonContiguousLayout = false
默认为true,正是这个属性让textview默认滚到末尾。
兴高采烈的改完属性,重新运行,结果发现还是有问题。
竟然是从第二行开始显示??!!接着我尝试加入滚动代码
textview.scrollRangeToVisible(NSMakeRange(0, 1))
尝试多次后发现,这段代码只有放在viewDidAppear中才能起作用(此时用户是能够看到滚动过程的!),我推测在viewDidLoad和viewWillAppear中textview还没有拿到最终的frame(我是用storyboard来构建页面的),使得在这期间无论修改allowsNonContiguousLayout还是scrollRangeToVisible都没有效果,因为此时的frame确实已经滚动到了顶端。只不过等viewDidAppear之后UI布局做了最重调整,而此时滚动过程已经结束。
大概猜到原因之后,解决方法自然加入layoutIfNeeded让UI控件提前计算出最终的frame
override func viewDidLoad() {
super.viewDidLoad()
textview.layoutIfNeeded()
textview.layoutManager.allowsNonContiguousLayout = false
textview.scrollRangeToVisible(NSMakeRange(0, 1))
}
注意,即便是使用layoutIfNeeded提前拿到textview的frame,也还需要加入scrollRangeToVisible才能最终达到想要的效果。我推测这是苹果AutoLayout的bug。说实话AutoLayout一开始出现的时候各种BUG,不过完全拥抱AutoLayout之后,布局这一块确实减少了很多工作量。希望iOS能够更加完善吧。