UIScrollView基本使用:
1.设置可以滚动的范围 contentSize
self.scrollView.contentSize = XXX.size;
2.设置内容的偏移量 contentOffset
作用1:控制内容滚动的位置 作用2:得知内容滚动的位置 self.scrollView.contentOffset = CGPointMake(0, -100);
3.设置滚动区域四周的滚动范围 contentInset
self.scrollView.contentInset = UIEdgeInsetsMake(10, 10, 10, 10);
4.指定控件是否只能在一个方向上滚动(默认NO)
self.scrollView.directionalLockEnabled = YES;
5.是否有弹簧效果
self.scrollView.bounces = NO; 不管有没有设置contentSize,总是有弹簧效果(下拉刷新) self.scrollView.alwaysBounceHorizontal = YES; self.scrollView.alwaysBounceVertical = YES;
6.当值是 YES 会自动滚动到 subview 的边界(默认NO)
self.scrollView.pagingEnabled = YES;
7.控制控件是否能滚动(默认YES)
self.scrollView.scrollEnabled = NO;
8.点击状态栏回到顶部(默认YES)
self.scrollView.scrollsToTop = YES;
9.是否显示滚动条
水平方向 self.scrollView.showsHorizontalScrollIndicator = NO; 垂直方向 self.scrollView.showsVerticalScrollIndicator = NO;
10.指定滚动条在scrollerView中的位置
self.scrollView.scrollIndicatorInsets=UIEdgeInsetsMake(64.0, 0.0, 44.0, 0.0);
11.设置滚动条样式
默认:灰色线包围黑色条
self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleDefault;
12.内边距
self.scrollView.contentInset = UIEdgeInsetsMake(100, 0, 50, 0);
13.自动调整宽高
self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
14.设置子控件不能滚动:
//UIScrollView设置子控件不跟随自己滚动 -(void)layoutSubviews { [super layoutSubviews]; for (UIView*view in self.subviews) { if ([view isKindOfClass:[UIImageView class]]) { CGRect rect = view.frame; rect.origin.y = self.contentOffset.y; view.frame = rect; } } }
15.手势冲突
//返回YES,则可以多个手势一起触发方法,返回NO则为互斥(比如外层UIScrollView名为mainScroll内嵌的UIScrollView名为subScroll,当我们拖动subScroll时,mainScroll是不会响应手势的(多个手势默认是互斥的),当下面这个代理返回YES时,subScroll和mainScroll就能同时响应手势,同时滚动,这符合我们这里的需求) - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; }
16.UIScrollView点击状态栏返回顶部
在iOS开发中,UIScrollView自带点击状态栏自动返回顶部的效果: BOOL scrollsToTop.
这个手势只能作用在一个scrollView上,当发现多个时,手势将会失效。
在实际应用中,我们可能会有多个scrollView,这时,系统默认的点击状态栏返回顶部效果就会失效,我们就得自己自定义控件来实现此功能了。
思路:①自定义一个Window②监听顶部窗口点击③找到参数View中所有的UIScrollView④让UIScrollView滚到最前面。
自定义一个Window
#import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface HKWindow : UIWindow + (void)show; + (void)hide; @end NS_ASSUME_NONNULL_END #import "HKWindow.h" #import "HKTopViewController.h" @implementation HKWindow // 全局对象 static UIWindow *topWindow_; + (void)initialize { topWindow_ = [[UIWindow alloc] init]; topWindow_.frame = [UIApplication sharedApplication].statusBarFrame; topWindow_.windowLevel = UIWindowLevelAlert; topWindow_.backgroundColor = [UIColor clearColor]; HKTopViewController *rootVc = [HKTopViewController sharedInstance]; topWindow_.rootViewController = rootVc; } + (void)show { topWindow_.hidden = NO; } + (void)hide { topWindow_.hidden = YES; } @end
HKTopViewController
#import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface HKTopViewController : UIViewController + (HKTopViewController *)sharedInstance; @end NS_ASSUME_NONNULL_END #import "HKTopViewController.h" @interface HKTopViewController () @end @implementation HKTopViewController + (HKTopViewController *)sharedInstance { static dispatch_once_t onceToken; static HKTopViewController * _sharedInstance; dispatch_once(&onceToken, ^{ _sharedInstance = [[self alloc] init]; }); return _sharedInstance; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UIWindow *window = [UIApplication sharedApplication].keyWindow; [self searchScrollViewInView:window]; } // 递归搜索所有view查找当前位置合适的scrollView - (void)searchScrollViewInView:(UIView *)view { for (UIScrollView *subView in view.subviews) { if ([subView isKindOfClass:[UIScrollView class]] && [self isShowingInKeyWindow:subView]) { //开始进行滚动 CGPoint offset = subView.contentOffset; offset.y = -subView.contentInset.top; [subView setContentOffset:offset animated:YES]; } //寻找子视图的子视图 [self searchScrollViewInView:subView]; } } // 根据位置判断是否合适 - (BOOL)isShowingInKeyWindow:(UIView *)view { UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; CGRect currentFrame = [keyWindow convertRect:view.frame fromView:view.superview]; CGRect winBounds = keyWindow.bounds; BOOL intersects = CGRectIntersectsRect(currentFrame, winBounds); return !view.isHidden && view.alpha > 0.01 && view.window == keyWindow && intersects; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } @end
17.ScrollView固定滚动方向
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGPoint point = scrollView.contentOffset; // 限制y轴不动 point.y = 0.f;//Y轴不动(不能左右滑动) //point.x = 0.f;//X轴不动(不能上下滑动) scrollView.contentOffset = point; }
17.UIScrollView自动布局
//scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
//UIScrollView做自动布局: 首先确定scrollView滚动范围 => 如何在stroboard对scrollView确定滚动范围 => 搞一个专门view去确定scrollView的滚动范围 => 如何确定:水平 和 垂直方向 => scrollView水平能否滚动: view的宽度 + 左右两边间距 才能确定scrollView水平滚动区域 => 垂直 = view的高度 + 上下两边间距 UIScrollView底层实现: @interface ViewController ()<UIScrollViewDelegate> @property (nonatomic, weak) UIView *scrollView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 模仿系统控件 => 怎么去使用 => 滚动scrollView,其实本质滚动内容 => 改bounds => 验证 // => 手指往上拖动,bounds y++ ,内容才会往上走 UIView *scrollView = [[UIView alloc] initWithFrame:self.view.bounds]; [self.view addSubview:scrollView]; _scrollView = scrollView; // 添加Pan手势 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [scrollView addGestureRecognizer:pan]; UISwitch *switchView = [[UISwitch alloc] init]; [scrollView addSubview:switchView]; } - (void)pan:(UIPanGestureRecognizer *)pan { // 获取手指的偏移量 CGPoint transP = [pan translationInView:pan.view]; // 修改bounds CGRect bounds = _scrollView.bounds; bounds.origin.y -= transP.y; _scrollView.bounds = bounds; // 复位 [pan setTranslation:CGPointZero inView:pan.view]; } #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ NSLog(@"%@",NSStringFromCGRect(scrollView.bounds)); NSLog(@"%@",NSStringFromCGPoint(scrollView.contentOffset)); }
18.UIScrollView当方向禁止向上或者向下滑动
//我们有时候可能会需要单方向的禁止滑动,但是官方直接提供的方法只能禁止滑动,在这里我们用UITableView 或者 UIScrollView 的代理方法 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ //到顶部后不再向上滑动 if (scrollView.contentOffset.y < 0) { [self.tableView setContentOffset:CGPointZero animated:NO]; } //到底部后不再向下滑动 if (scrollView.contentOffset.y + CGRectGetHeight(self.udView.tableView.frame) >scrollView.contentSize.height){ [self.tableView setContentOffset:CGPointMake(selftableView.contentOffset.x,self.tableView.contentSize.height - CGRectGetHeight(self.tableView.frame)) animated:NO]; } }
Swift-版
func scrollViewDidScroll(scrollView: UIScrollView) { // 禁止下拉 if scrollView.contentOffset.y <= 0 { scrollView.contentOffset.y = 0 } // 禁止上拉 if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.bounds.size.height { scrollView.contentOffset.y = scrollView.contentSize.height - scrollView.bounds.size.height } }