UIScrollView詳解


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
    }
}

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM