天天看点

UIScrollView + AutoLayout结合使用UIScrollView特性AutoLayoutUIScrollView在AutoLayout中的特殊用法具体实现总结

UIScrollView特性

UIScrollView(包括它的子类 UITableView 和 UICollectionView)是 iOS 开发中最常用也是最有意思的 UI 组件,大部分 App 的核心界面都是基于三者之一或三者的组合实现。UIScrollView 是 UIKit 中为数不多能响应滑动手势的 view,相比自己用 UIPanGestureRecognizer 实现一些基于滑动手势的效果,用 UIScrollView 的优势在于 bounce 和 decelerate 等特性可以让 App 的用户体验与 iOS 系统的用户体验保持一致。

特别是在当前屏幕无法完全显示内容的时候,需要动态计算高度,来设定UIScrollView的contentSize,这样实现scrollview动态适应高度变化。

AutoLayout

iPhone 5 刚出来的时候,大部分不支持横屏的 App 都不需要做太多的适配工作,因为屏幕宽度没有变,table view 多个 cell 也不需要加 code。但是在 iPhone 6 和 iPhone 6 Plus 发布以后,多分辨率适配终于不再是 Android 开发的专利了。于是,从 iOS 6 起就存在的 Auto Layout 终于有了用武之地。

Auto Layout的使用已经非常普遍,特别在当下,iphone设备分辨率和屏幕大小不统一,应用需要适配不同的设备,Auto Layout的功能就显现出来了。

UIScrollView在AutoLayout中的特殊用法

当我们在Auto Layout中使用到UIScrollView的时候,会发现无法给scrollView中的subViews添加各种约束,还会出现各种问题,例如:约束失效等问题,这里我们就需要了解UIScrollView的特别之处。

UIScrollView 在 Auto Layout 是一个很特殊的 view,对于 UIScrollView 的 subview 来说,它的leading/trailing/top/bottom space 是相对于 UIScrollView 的 contentSize 而不是 bounds 来确定的,所以当你尝试用 UIScrollView 和它 subview 的 leading/trailing/top/bottom 来互相决定大小的时候,就会出现「Has ambiguous scrollable content width/height」的 warning。

正确的姿势是用 UIScrollView 外部的 view 或 UIScrollView 本身的 width/height 确定 subview 的尺寸,进而确定 contentSize。因为 UIScrollView 本身的 leading/trailing/top/bottom 变得不好用,所以我习惯的做法是在 UIScrollView 和它原来的 subviews 之间增加一个 content view。

因此,我们需要在UIScrollView中添加一个contentView,然后再contentview中添加子视图,给视图设定约束,这里就会出现一个问题,我们怎么让UIScrollView滚动显示完视图,还需要设定UIScrollView的contentSize吗?

答案是NO,原因是,此时scrollView会完全显示contentView的内容,也就是说,contentView的size发生变化时,scrollView的contentSize同样也会发生变化,就是为了完全实现contentView的内容,也就是通过调整 content view 的 size(可以是 constraint 的 IBOutlet)来调整 contentSize,下面就来看看具体的实现吧!

具体实现

结合Auto Layout创建UIScrollView,为scrollView设定约束值。

我这里就是让scrollView填充整个view,并且在scrollView上添加contentView,为contentView设定约束值。关于约束值的具体设定,大家可以在我的项目中查看。
UIScrollView + AutoLayout结合使用UIScrollView特性AutoLayoutUIScrollView在AutoLayout中的特殊用法具体实现总结

contentView的size约束使用IBOutlet设定成属性值

这里这样做主要就是为了在代码中,动态修改size的宽和高。
UIScrollView + AutoLayout结合使用UIScrollView特性AutoLayoutUIScrollView在AutoLayout中的特殊用法具体实现总结

动态设定size的值

这里我们需要查看UIViewController的文档,发现在iOS 6之后加入了一个函数,这是官方介绍:也就是在Auto Layout使用中,在viewController中动态修改约束值。
@interface UIViewController (UIConstraintBasedLayoutCoreMethods)
/* Base implementation sends -updateConstraints to the view.
    When a view has a view controller, this message is sent to the view controller during 
     the autolayout updateConstraints pass in lieu of sending updateConstraints directly
     to the view.
    You may override this method in a UIViewController subclass for updating custom 
     constraints instead of subclassing your view and overriding -[UIView updateConstraints].
    Overrides must call super or send -updateConstraints to the view.
 */
- (void)updateViewConstraints NS_AVAILABLE_IOS(_0);
@end
           
我们这里的做法就是重写这个函数,在这个方法里面通过计算文本高度来设定约束值,也就是contentView的宽和高的约束值。
//设置约束值
- (void)updateViewConstraints{
    [super updateViewConstraints];
    //计算文本高度
    CGRect rect = [_activity.content boundingRectWithSize:CGSizeMake(self.view.frame.size.width - , ) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:]} context:nil];
    self.viewWidth.constant = self.view.frame.size.width - ;
    self.viewHeight.constant = self.content.frame.origin.y + rect.size.height;
}
           
这里我用到了一个计算文本高度的方法,具体的介绍大家可以到网上查阅,这个还是比较常用的。

总结

到这里差不多就介绍完了,也许讲的不是很详细,如果大家想看看具体的代码,可以去查看我的项目。

项目地址,这里面有具体的代码和实现