UIScrollView实现分页

1. 只要将UIScrollView的pageEnabled属性设置为YES,UIScrollView会被分割成多个独立页面,里面的内容就能进行分页展示
2. 一般会配合UIPageControl增强分页效果,UIPageControl常用属性如下:

一共有多少页

@property(nonatomic) NSInteger numberOfPages;

当前显示的页码

@property(nonatomic) NSInteger currentPage;

只有一页时,是否需要隐藏页码指示器

@property(nonatomic) BOOL hidesForSinglePage;

其他页码指示器的颜色

@property(nonatomic,retain) UIColor *pageIndicatorTintColor;

当前页码指示器的颜色

@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;

3. 代码示例:

@interface ViewController ()
@end
@implementation ViewController
// 控制器中代码:
- (void)viewDidLoad {
    [super viewDidLoad];
    
    ZZFPageView *pageView = [ZZFPageView pageView];
    pageView.frame = CGRectMake(37, 50, 250, 200);
    pageView.imageNames = @[@"img_00", @"img_01", @"img_02"];
    pageView.otherColor = [UIColor grayColor];
    pageView.currentColor = [UIColor orangeColor];
    pageView.currentColor = [UIColor blueColor];
    
    [self.view addSubview:pageView]; 
    pageView.imageNames = @[@"img_00", @"img_01", @"img_02", @"img_03", @"img_04"]; 
   //pageView.imageNames = @[@"img_00"];   
   // pageView.frame = CGRectMake(0, 0, 100, 100); 这些代码测试LayoutsubViews方法什么时候调用
}
@end
//封装View
@interface ZZFPageView : UIView

+ (instancetype)pageView;

/** 图片名字 */
@property (nonatomic, strong) NSArray *imageNames;
/** 其他圆点颜色 */
@property (nonatomic, strong) UIColor *otherColor;
/** 当前圆点颜色 */
@property (nonatomic, strong) UIColor *currentColor;
@end
@interface XMGPageView() <UIScrollViewDelegate>
//xib中的控件 在xib中设置了scrollView的代理是封装的View  代理的对象是id类型,可以不是控制器
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@end
@implementation XMGPageView
+ (instancetype)pageView
{
    return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject];
}
- (void)layoutSubviews
{
    [super layoutSubviews];    
    // 设置scrollView的frame
    self.scrollView.frame = self.bounds;    
    // 获得scrollview的尺寸
    CGFloat scrollW = self.scrollView.frame.size.width;
    CGFloat scrollH = self.scrollView.frame.size.height;    
    // 设置pageControl
    CGFloat pageW = 100;
    CGFloat pageH = 20;
    CGFloat pageX = scrollW - pageW;
    CGFloat pageY = scrollH - pageH;
    self.pageControl.frame = CGRectMake(pageX, pageY, pageW, pageH);
    
    // 设置内容大小
    self.scrollView.contentSize = CGSizeMake(self.imageNames.count * scrollW, 0);
    
    // 设置所有imageView的frame
    for (int i = 0; i<self.scrollView.subviews.count; i++) {
        UIImageView *imageView = self.scrollView.subviews[i];
        imageView.frame = CGRectMake(i * scrollW, 0, scrollW, scrollH);
    }
}

#pragma mark - setter方法的重写
- (void)setImageNames:(NSArray *)imageNames
{
    _imageNames = imageNames;
// 移除之前的所有imageView
    // 让subviews数组中的所有对象都执行removeFromSuperview方法 
    [self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    
    // 根据图片名创建对应个数的imageView
    for (int i = 0; i<imageNames.count; i++) {
        UIImageView *imageView = [[UIImageView alloc] init];
        imageView.image = [UIImage imageNamed:imageNames[i]];
        [self.scrollView addSubview:imageView];
    }
    
    // 设置总页数
    self.pageControl.numberOfPages = imageNames.count;
//    if (imageNames.count <= 1) {
//        self.pageControl.hidden = YES;
//    } else {
//        self.pageControl.hidden = NO;
//    }
//    self.pageControl.hidden = imageNames.count <= 1;
//    self.pageControl.hidesForSinglePage = YES;
}

- (void)setCurrentColor:(UIColor *)currentColor
{
    _currentColor = currentColor;
    
    self.pageControl.currentPageIndicatorTintColor = currentColor;
}

- (void)setOtherColor:(UIColor *)otherColor
{
    _otherColor = otherColor;
    
    self.pageControl.pageIndicatorTintColor = otherColor;
}
//代理方法可以在封装的view中
#pragma mark - <UIScrollViewDelegate>
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    self.pageControl.currentPage = (int)(scrollView.contentOffset.x / scrollView.frame.size.width + 0.5);
}
@end

4. 补充

1. 注意:代理一般是控制器,因为他管理所有的控件,但是也可以不是 代理是没有限制的,封装的时候,代理很多都不是控制器

2. 只有set方法才能监听别人传过来的值【为什么set赋值就能重新赋值】

3. 封装:xib和纯代码是一样的, frame设置最好在LayoutsubViews方法中

4. set方法重新赋值是:注意刷新或者重新传值得时候就会创建,

5. 在layout中计算frame是原来的写法

6.重点:过期代码的设置【过期是不建议使用,不能把原来的代码删除了】

LayoutsubViews什么时候调用:利用runloop 收集frame的上所有的修改,runloop释放前调用。

封装view中:if shop.icon等于nil    ;   uisocrollView也可以重用吗

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    ZZFLabel *label = [[ZZFLabel alloc] init];
    label.frame = CGRectMake(0, 100, 100, 20);
    label.text = @"原价:998¥";
    [self.view addSubview:label];
    
    ZZFPageView *pageView = [ZZFPageView pageView];
    pageView.frame = CGRectMake(37, 50, 250, 200);
    pageView.imageNames = @[@"img_00", @"img_01", @"img_02"];
    pageView.otherColor = [UIColor grayColor];
    pageView.currentColor = [UIColor orangeColor];
    [self.view addSubview:pageView];
    self.pageView = pageView;
}
//1. 消息循环\运行循环 
@end
// 框架:
// 1.苹果官方的框架:UIKit
// 2.自定义框架
// 3.第三方框架:流媒体

#import "XMGPageView.h"

@interface XMGPageView() <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@end

@implementation XMGPageView
/**  讲的顺序
 * 1. 当控件通过代码创建时,就会调用这个方法
 *    当控件通过代码创建时,想做一些初始化操作。应该在这个方法中执行
 */
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setup];
        
        // 添加子控件代码
    }
    return self;
}
/**
 * 初始化代码
 */
- (void)setup
{
    self.scrollView.backgroundColor = [UIColor redColor];
}

/**
 * 2. 当控件是通过xib\storyboard创建时,会调用这个方法来初始化控件
 
 注意;xib加载的不会去init,因为去init就会去initframe
 */
- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
    }
    //这个里面能监听到控件的加载,但是不是完整的加载,因为这个方法运行完,有的xib中的控件没有加载到,例如scrollView 他就没有加载 打印一下就知道了
    return self;
}
/**
 * 当控件从xib\storyboard中创建完毕时,就会调用这个方法
 * 当控件从xib\storyboard中创建完毕后的初始化操作。应该在这个方法中执行
 */
- (void)awakeFromNib
{
    //xib中的控件就已经加载完了,连线已经完成,就会调用这个方法
    [self setup];
}



+ (instancetype)pageView
{
    return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject];
}

/**
 * 当控件的尺寸发生改变的时候,会自动调用这个方法
 */
- (void)layoutSubviews
{
    [super layoutSubviews];
    
    // 设置scrollView的frame
    self.scrollView.frame = self.bounds;
    
    // 获得scrollview的尺寸
    CGFloat scrollW = self.scrollView.frame.size.width;
    CGFloat scrollH = self.scrollView.frame.size.height;
    
    // 设置pageControl
    CGFloat pageW = 100;
    CGFloat pageH = 20;
    CGFloat pageX = scrollW - pageW;
    CGFloat pageY = scrollH - pageH;
    self.pageControl.frame = CGRectMake(pageX, pageY, pageW, pageH);
    
    // 设置内容大小
    self.scrollView.contentSize = CGSizeMake(self.imageNames.count * scrollW, 0);
    
    // 设置所有imageView的frame
    for (int i = 0; i<self.scrollView.subviews.count; i++) {
        UIImageView *imageView = self.scrollView.subviews[i];
        imageView.frame = CGRectMake(i * scrollW, 0, scrollW, scrollH);
    }
}

#pragma mark - setter方法的重写
- (void)setImageNames:(NSArray *)imageNames
{
    _imageNames = imageNames;
    
    // 移除之前的所有imageView
    // 让subviews数组中的所有对象都执行removeFromSuperview方法
    [self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    
    // 根据图片名创建对应个数的imageView
    for (int i = 0; i<imageNames.count; i++) {
        UIImageView *imageView = [[UIImageView alloc] init];
        imageView.image = [UIImage imageNamed:imageNames[i]];
        [self.scrollView addSubview:imageView];
    }
    
    // 设置总页数
    self.pageControl.numberOfPages = imageNames.count;
//    if (imageNames.count <= 1) {
//        self.pageControl.hidden = YES;
//    } else {
//        self.pageControl.hidden = NO;
//    }
//    self.pageControl.hidden = imageNames.count <= 1;
//    self.pageControl.hidesForSinglePage = YES;
}

- (void)setCurrentColor:(UIColor *)currentColor
{
    _currentColor = currentColor;
    
    self.pageControl.currentPageIndicatorTintColor = currentColor;
}

- (void)setOtherColor:(UIColor *)otherColor
{
    _otherColor = otherColor;
    
    self.pageControl.pageIndicatorTintColor = otherColor;
}

#pragma mark - <UIScrollViewDelegate>
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    self.pageControl.currentPage = (int)(scrollView.contentOffset.x / scrollView.frame.size.width + 0.5);
}
@end
#import <UIKit/UIKit.h>

@interface XMGPageView : UIView
+ (instancetype)pageView;
/** 图片名字 */
@property (nonatomic, strong) NSArray *imageNames;
/** 其他圆点颜色 */  设置过期的代码
@property (nonatomic, strong) UIColor *otherColor NS_DEPRECATED_IOS(2_0, 2_0, "建议使用nbColor");
/** 当前圆点颜色 */
@property (nonatomic, strong) UIColor *currentColor;
@end

 

7. 封装的思想:既支持纯代码也支持xib的框架:

@interface ZZFLabel : UILabel
@end
@implementation ZZFLabel
// 1. 纯代码调用
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setup];
    }
    return self;
}

// 2. 加载xib的时候调用  加载xib的时候如果不写这个方法,控件的属性不会被设置
- (void)awakeFromNib
{
    [self setup];
}

- (void)setup
{
    self.textColor = [UIColor redColor];
    self.textAlignment = NSTextAlignmentCenter;
}

//绘画
- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    
    [self.textColor set];
    CGFloat w = rect.size.width;
    CGFloat h = rect.size.height;
    UIRectFill(CGRectMake(0, h * 0.3, w, 1));
}
@end

 

快捷方法

  1. 模拟器缩放: 按住option,单击就可以了
  2. 如果出现中文,后面的就不会提示了