UIScrollView 的基本使用

    xiaoxiao2021-03-25  95

    UIScrollView 基本使用

    UIScrollView 的三个属性

    contentSize 设置滚动区域,只有设置了滚动区域才能够滚动contentOffset 设置滚动内容偏移,决定当前显示的内容contentInset 设置滚动外框的偏移

    UIScrollView 无法滚动原因

    UIScrollView 设置弹簧效果 & 滚动指示器

    常用属性演练

    准备工作

    新建项目在 ViewController 中实现以下代码,添加 scrollView @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; } #pragma mark - 设置界面 - (void)setupUI { // 1. 创建 UIScrollView UIScrollView *sv = [[UIScrollView alloc] initWithFrame:self.view.bounds]; sv.backgroundColor = [UIColor blueColor]; [self.view addSubview:sv]; } @end 添加 imageView // 2. 添加 imageView UIImage *image = [UIImage imageNamed:@"002"]; // initWithImage 方法创建的 imageView 会根据 image 的大小自动调整大小 UIImageView *iv = [[UIImageView alloc] initWithImage:image]; // 将 图像视图 添加到 滚动视图上 [sv addSubview:iv];

    运行程序,会发现不会滚动,那么如何滚动呢?

    探索头文件

    NS_CLASS_AVAILABLE_IOS(2_0) @interface UIScrollView : UIView <NSCoding> /// The point at which the origin of the content view is offset from the origin of the scroll view. /// 内容视图原点(origin)所在的偏移位置,相对于 scroll view 的 origin,默认是 CGPointZero @property(nonatomic) CGPoint contentOffset; // default CGPointZero /// The size of the content view /// 内容视图的大小,默认是 CGSizeZero @property(nonatomic) CGSize contentSize; // default CGSizeZero /// The distance that the content view is inset from the enclosing scroll view. /// 内容视图围绕(enclosing) scroll view 的距离,默认值是 UIEdgeInsetsZero @property(nonatomic) UIEdgeInsets contentInset; // default UIEdgeInsetsZero. add additional scroll area around content 定义属性,方便后续代码演练 @property (nonatomic, weak) UIScrollView *scrollView; @property (nonatomic, weak) UIImageView *imageView; 在 setupUI 方法中使用成员变量记录局部变量 _scrollView = sv; _imageView = iv; 新建 demoScrollView 方法并在 viewDidLoad 方法中调用 - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; [self demoScrollView]; } #pragma mark - 演练 scrollview - (void)demoScrollView { }

    三个属性演练

    contentSizecontentOffsetcontentInset

    contentSize

    在 demoScrollView 中实现以下方法 - (void)demoScrollView { // 1. 设置 contentSize // 让 scrollView 的 contentSize 等于 图像视图的大小 // 设置了滚动视图的 contentSize 之后,滚动视图就能够滚动了 _scrollView.contentSize = _imageView.bounds.size; }

    结论

    设置了滚动视图的 contentSize 之后,滚动视图就能够滚动了

    没有 contentSize,scrollView 就不知道要滚多远

    单独设置 contentSize 的 width // contentSize 的 width 决定了水平方向能滚多远 _scrollView.contentSize = CGSizeMake(_imageView.bounds.size.width, 0); 单独设置 contentSize 的 height // contentSize 的 height 决定了垂直方向能滚多远 _scrollView.contentSize = CGSizeMake(0, _imageView.bounds.size.height);

    结论

    scrollView 要滚动就必须设置了滚动视图的 contentSizecontentSize 的 width 决定了水平方向滚动距离contentSize 的 height 决定了垂直方向滚动距离 方法名重构 —— 快捷键 cmd + shift + e /// 演示 contentSize /// /// 结论: /// - scrollView 要滚动就必须设置了滚动视图的 contentSize /// - contentSize 的 width 决定了水平方向滚动距离 /// - contentSize 的 height 决定了垂直方向滚动距离 - (void)demoContentSize { // 1. 设置 contentSize // 让 scrollView 的 contentSize 等于 图像视图的大小 // 设置了滚动视图的 contentSize 之后,滚动视图就能够滚动了 _scrollView.contentSize = _imageView.bounds.size; // contentSize 的 width 决定了水平方向能滚多远 // _scrollView.contentSize = CGSizeMake(_imageView.bounds.size.width, 0); // contentSize 的 height 决定了垂直方向能滚多远 // _scrollView.contentSize = CGSizeMake(0, _imageView.bounds.size.height); }

    contentOffset

    新建方法 demoContentOffset 并在 viewDidLoad 调用 - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; [self demoContentSize]; [self demoContentOffset]; } #pragma mark - 演练 scrollview /// 演示 contentOffset - (void)demoContentOffset { } 增加演示按钮 /// 演示 contentOffset - (void)demoContentOffset { // 1. 增加演示按钮 UIButton *btn = [UIButton buttonWithType:UIButtonTypeInfoLight]; btn.center = self.view.center; [self.view addSubview:btn]; [btn addTarget:self action:@selector(clickOffsetButton) forControlEvents:UIControlEventTouchUpInside]; } /// 点击测试 offset 按钮 - (void)clickOffsetButton { } 实现代码修改 contentOffset /// 点击测试 offset 按钮 - (void)clickOffsetButton { // 修改 scrollView 的 contentOffset _scrollView.contentOffset = CGPointMake(50, 50); // bounds 决定了内部控件布局的原点坐标 NSLog(@"%@", NSStringFromCGRect(_scrollView.bounds)); } 修改代码,递增 contentOffset 的变化 // 2> 递增 contentOffset CGPoint p = _scrollView.contentOffset; p.x += 50; p.y += 50; _scrollView.contentOffset = p; 修改 NSLog // bounds 决定了内部控件布局的原点坐标 // scrollView 的 contentOffset 属性本质上就是 bounds 的原点 NSLog(@"%@ - %@", NSStringFromCGRect(_scrollView.bounds), NSStringFromCGPoint(_scrollView.contentOffset));

    结论

    scrollView 通过修改 contentOffset 调整内部视图的坐标位置,从而给用户产生一种视觉上的滚动的效果contentOffset 的值本质上就是 bounds 的原点(origin) 值,苹果在为了方便程序员的理解,增加了这个属性 文档释义:contentOffset:内容视图原点(origin)所在的偏移位置,相对于 scroll view 的 origin,默认是 CGPointZero

    contentOffset 相关方法

    探索头文件 /// 以恒定速度动画移动到新的 offset - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated; // animate at constant velocity to new offset /// 滚动到可见区域(靠近边缘-不会滚动到边缘外侧),如果当前区域完全可见,则什么也不做 - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated; // scroll so rect is just visible (nearest edges). nothing if rect completely visible

    苹果头文件的特点:越是重要的属性和方法就越靠上

    新建测试方法 /// 测试 offset 相关方法 - (void)testSetOffsetMethod { } 修改按钮监听方法 [btn addTarget:self action:@selector(testSetOffsetMethod) forControlEvents:UIControlEventTouchUpInside]; 实现方法,测试 setContentOffset:animated: 方法 /// 测试 offset 相关方法 - (void)testSetOffsetMethod { // 1. 测试 setContentOffset CGFloat x = arc4random_uniform(_imageView.bounds.size.width); CGFloat y = arc4random_uniform(_imageView.bounds.size.height); // 利用系统默认的动画效果,动画时长不能修改 [_scrollView setContentOffset:CGPointMake(x, y) animated:YES]; } 自定义动画效果 // 2> 自定义动画效果 [UIView animateWithDuration:1.0 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{ _scrollView.contentOffset = CGPointMake(x, y); } completion:nil]; 新建方法 testScrollRectMethod - (void)testScrollRectMethod { // 传入当前完全可见区域,什么也不发生 [_scrollView scrollRectToVisible:_scrollView.bounds animated:YES]; } 随机区域 // 2> 随机区域 CGFloat x = arc4random_uniform(_imageView.bounds.size.width); CGFloat y = arc4random_uniform(_imageView.bounds.size.height); CGRect rect = CGRectMake(x, y, _scrollView.bounds.size.width, _scrollView.bounds.size.height); [_scrollView scrollRectToVisible:rect animated:YES];

    contentInset

    /// 内容视图围绕(enclosing) scroll view 的距离,默认值是 UIEdgeInsetsZero @property(nonatomic) UIEdgeInsets contentInset; // default UIEdgeInsetsZero. add additional scroll area around content 新增方法 demoContentInset 并且在 viewDidLoad 调用 - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; [self demoContentSize]; [self demoContentOffset]; [self demoContentInset]; } #pragma mark - 演练 scrollview /// 演示 contentInset - (void)demoContentInset { } 实现方法 demoContentInset /// 演示 contentInset - (void)demoContentInset { UIEdgeInsets inset = UIEdgeInsetsMake(50, 50, 50, 50); // 边距设置了,但是初始没有效果,需要拖拽一下才有效果 _scrollView.contentInset = inset; } 利用 contentOffset 设置初始位置 // 设置 contentOffset 调整到边距对应位置 _scrollView.contentOffset = CGPointMake(-inset.left, -inset.top);

    结论

    scrollView 通过修改 contentInset 调整内部和边缘的偏移

    设置边距之后,初始没有效果,需要拖拽一下才有效果

    可以通过设置 contentOffset 调整初始位置

    scrollView 与内容相关的三个属性示意图如下:

    结论

    scrollView 要滚动就必须设置了滚动视图的 contentSize

    contentSize 的 width 决定了水平方向滚动距离contentSize 的 height 决定了垂直方向滚动距离

    scrollView 通过修改 contentOffset 调整内部视图的坐标位置,从而给用户产生一种视觉上的滚动的效果

    contentOffset 的值本质上就是 bounds 的原点(origin) 值,苹果在为了方便程序员的理解,增加了这个属性

    scrollView 通过修改 contentInset 调整内部和边缘的偏移

    设置边距之后,初始没有效果,需要拖拽一下才有效果可以通过设置 contentOffset 调整初始位置

    设置弹簧效果 & 滚动指示器

    探索头文件 /// 默认 YES @property(nonatomic) BOOL bounces; // default YES. if YES, bounces past edge of content and back again /// 始终垂直弹,默认是 NO,如果设置成 YES,即使内容比区域小,同样允许垂直方向弹动 @property(nonatomic) BOOL alwaysBounceVertical; // default NO. if YES and bounces is YES, even if content is smaller than bounds, allow drag vertically /// 始终水平弹,默认是 NO,如果设置成 YES,即使内容比区域小,同样允许水平方向弹动 @property(nonatomic) BOOL alwaysBounceHorizontal; // default NO. if YES and bounces is YES, even if content is smaller than bounds, allow drag horizontally /// 是否允许滚动,默认是 YES,关闭之后禁止任何拖拽 @property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled; // default YES. turn off any dragging temporarily /// 显示水平滚动指示器 @property(nonatomic) BOOL showsHorizontalScrollIndicator; // default YES. show indicator while we are tracking. fades out after tracking /// 显示垂直滚动指示器 @property(nonatomic) BOOL showsVerticalScrollIndicator; // default YES. show indicator while we are tracking. fades out after tracking /// 滚动指示器边距 @property(nonatomic) UIEdgeInsets scrollIndicatorInsets; // default is UIEdgeInsetsZero. adjust indicators inside of insets 新建方法,并且在 viewDidLoad 调用 - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; [self demoContentSize]; [self demoContentOffset]; [self demoContentInset]; [self demoBounces]; } #pragma mark - 演练 scrollview /// 演示弹簧效果 - (void)demoBounces { } 实现方法,禁止弹簧效果 /// 演示弹簧效果 - (void)demoBounces { // 1. 禁止弹簧效果 _scrollView.bounces = NO; } 测试始终弹动 // 2. 测试始终允许弹簧效果 // 取消 contentSize 无法滚动 _scrollView.contentSize = CGSizeZero; _scrollView.alwaysBounceVertical = YES; _scrollView.alwaysBounceHorizontal = YES; 测试禁止滚动属性 _scrollView.scrollEnabled = NO;

    如果禁止滚动,弹簧效果同样失效

    测试滚动指示器 // 3. 滚动指示器 // 1> 禁用垂直滚动指示器 _scrollView.showsVerticalScrollIndicator = NO; // 1> 禁用水平滚动指示器 _scrollView.showsHorizontalScrollIndicator = NO;

    查看视图层次结构会发现,禁用指示器之后,那两个 UIImageView 不见了

    结论

    苹果是用 imageView 实现的水平和垂直指示器

    转载请注明原文地址: https://ju.6miu.com/read-40328.html

    最新回复(0)