iOS 利用UIScrollView和UIPageViewCon

2019-10-23  本文已影响0人  HCL黄
11.gif

如上图,算了,来不及解释了,直接上代码

第一步,创建顶部选项视图

typedef void(^TabClickBlock)(NSInteger index);
@interface LATabScrollView : UIScrollView
/**
 titles:所有标题数组
 index: 当前选中的下标
 clickBlock:点击回调
 */
-(void)configParameterFrame:(CGRect)frame titles:(NSArray<NSString*> *)titles index:(NSInteger)index block:(TabClickBlock) clickBlock;

/** 点击滚动到指定index */
-(void)tabOffset:(NSInteger)index;

@end
@interface LATabScrollView ()
<
UIScrollViewDelegate
>
@property (nonatomic,strong) NSMutableArray *labelM;

@property (nonatomic,strong) NSArray<NSString*> *titles;
/** 记录位置下标 */
@property (nonatomic, assign) NSInteger tagIndex;
/** 点击回调 */
@property (nonatomic, copy) TabClickBlock clickBlock;
@end

CGFloat margin = 16;

@implementation LATabScrollView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setupUI];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self setupUI];
    }
    return self;
}

- (void)setupUI {
    self.backgroundColor = [UIColor blueColor];
    self.delegate = self;
    self.showsVerticalScrollIndicator = NO;
    self.showsHorizontalScrollIndicator = NO;
}

/**
 titles:所有标题数组
 index: 当前选中的下标
 clickBlock:点击回调
 */
-(void)configParameterFrame:(CGRect)frame titles:(NSArray<NSString*> *)titles index:(NSInteger)index block:(TabClickBlock) clickBlock {
    self.titles = titles;
    self.clickBlock = clickBlock;
    self.tagIndex = index;
    self.frame = frame;
    
    for (NSInteger i = 0; i < titles.count; i++) {
        UILabel *lbl = [[UILabel alloc]init];
        lbl.tag = i;
        lbl.textAlignment = NSTextAlignmentCenter;
        lbl.text = titles[i];
        lbl.textColor=[UIColor lightGrayColor];
        lbl.font = [UIFont systemFontOfSize:14];
        CGSize tabSize = [lbl.text sizeWithAttributes:@{NSFontAttributeName:lbl.font}];
        if (i == 0) {
            lbl.frame = CGRectMake(margin, 0, tabSize.width + 1.5, frame.size.height);
        }else {
            UILabel *preLbl = self.labelM[i - 1];
            lbl.frame = CGRectMake(CGRectGetMaxX(preLbl.frame) + margin, 0, tabSize.width + 1.5, frame.size.height);
        }
        [self addSubview:lbl];
        [self.labelM addObject:lbl];
        
        // 添加点击事件
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(menuAction:)];
        lbl.userInteractionEnabled=YES;
        [lbl addGestureRecognizer:tap];
    }
    
    UILabel *lastLbl = [self.labelM lastObject];
    CGFloat maxWidth = CGRectGetMaxX(lastLbl.frame) + margin;
    
    // 设置内容宽度
    self.contentSize = CGSizeMake(maxWidth, 0);
    
    // 默认滚到对应的下标
    [self tabOffset:index];
}

-(void)menuAction:(id)sender{
    UITapGestureRecognizer *tap = (UITapGestureRecognizer*)sender;
    UILabel *lbl = (UILabel*)tap.view;
    NSUInteger index = lbl.tag;   //获取上面view设置的tag
    
    [self tabOffset:index];
    
    if (self.clickBlock){
        self.clickBlock(index);
    }
}

/** 点击滚动到指定index */
-(void)tabOffset:(NSInteger)index{
    if (self.labelM.count == 0) { return; }
    if (index > self.titles.count-1) {
        index = self.titles.count-1;
    }
    
    for (NSInteger i = 0; i < self.labelM.count; i++) {
        UILabel *lbl = self.labelM[i];
        if (index == i) {
            lbl.textColor=[UIColor whiteColor];
            lbl.font = [UIFont boldSystemFontOfSize:14];
        }else {
            lbl.textColor=[UIColor lightGrayColor];
            lbl.font = [UIFont systemFontOfSize:14];
        }
    }
    
    // 获取scrollview宽度
    NSInteger selfW = self.frame.size.width;
    
    UILabel *lbl = self.labelM[index];
    NSInteger lblW = lbl.frame.size.width;
    
    // 获取当前点击的tab所处的位置大小
    CGFloat lblMinX = CGRectGetMinX(lbl.frame);
    // 判断tab是否处于大于屏幕一半的位置,并计算出偏移量
    CGFloat offsetX_halfSelfW = lblMinX - selfW/2;
    //当tab偏移量不足tab宽度时,计算出最小的偏移量
    CGFloat itemOffset = offsetX_halfSelfW + lblW/2;
    NSInteger contentW = self.contentSize.width;
    
    //当偏移量>0的时候,
    if(offsetX_halfSelfW > 0){
        //假如偏移量小于一个tab的宽度,说明还没有到最初始位置,可以执行偏移
        if(offsetX_halfSelfW < lblW){
            if (contentW < selfW) { return; } // 内容不足以超出屏幕
//            NSLog(@"setContentOffset 1");
            [self setContentOffset:CGPointMake(itemOffset, 0) animated:YES];
            return;
        }
        //获取偏移的页数,减1的作用是我们的偏移是从0开始的,所以需要减去一个屏幕长度
        NSInteger page = contentW/selfW - 1;
        //获取最后一页的偏移量
        NSInteger last_page_offsetX = contentW % selfW;
        //获取到最大偏移量
        NSInteger maxOffsetX = page * selfW + last_page_offsetX;
        //假如我们的计算的偏移量小于最大偏移,说明是可以偏移的
        if(itemOffset <= maxOffsetX){
            //假如偏移量大于一个tab的宽度,判断
            if(itemOffset <= lblW){  //当点击的偏移量小于tab的宽度的时候,归零偏移量
//                NSLog(@"setContentOffset 2");
                [self setContentOffset:CGPointMake(0, 0) animated:YES];
                return;
            }else{
//                NSLog(@"setContentOffset 3");
                [self setContentOffset:CGPointMake(itemOffset, 0) animated:YES];
            }
            
        }else{
            if (maxOffsetX < 0) {
                return;
            }
//            NSLog(@"setContentOffset 4");
            [self setContentOffset:CGPointMake(maxOffsetX, 0) animated:YES];
        }
    }else if(offsetX_halfSelfW < 0){
        //判断往后滚的偏移量小于0但是却和半个tab宽度之和要大于0的时候,说明还可以进行微调滚动,
        if(itemOffset>0){
//            NSLog(@"setContentOffset 5");
            [self setContentOffset:CGPointMake(itemOffset, 0) animated:YES];
            return;
        }
//        NSLog(@"setContentOffset 6");
        //最小偏移小于0,说明往前滚,将偏移重置为初始位置
        [self setContentOffset:CGPointMake(0, 0) animated:YES];
    }else{
//        NSLog(@"setContentOffset 7");
        [self setContentOffset:CGPointMake(0, 0) animated:YES];
    }
    
    self.tagIndex=index;
}

#pragma mark - Property

- (NSMutableArray *)labelM {
    if (_labelM == nil) {
        _labelM = [NSMutableArray array];
    }
    return _labelM;
}
                
@end

第二步,创建内容视图

typedef void(^TabSwitchBlcok)(NSInteger index);

@interface LATabContentView : UIView

@property (nonatomic,strong)TabSwitchBlcok tabSwitch;

-(void)configParam:(NSMutableArray<UIViewController*>*)controllers index:(NSInteger)index block:(TabSwitchBlcok)tabSwitch;

/**
 更新滚动到index页面
 */
-(void)updateTab:(NSInteger)index;
@end
@interface LATabContentView ()
<
UIPageViewControllerDelegate,
UIPageViewControllerDataSource
>

@property (nonatomic, strong) UIPageViewController *pageController;
/** 内容页数组 */
@property (nonatomic, strong) NSArray<UIViewController*> *controllers;
/** 记录上一次的下标 */
@property (nonatomic, assign) NSInteger oriIndex;

@end

@implementation LATabContentView

- (instancetype)initWithFrame:(CGRect)frame {
    self =[super initWithFrame:frame];
    if(self){
        [self initView];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    self.pageController.view.frame = self.bounds;
}

-(void)initView{
    // 配置UIPageViewController的基本信息
    self.pageController=[[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageController.delegate = self;
    self.pageController.dataSource = self;
    self.pageController.view.backgroundColor = [UIColor whiteColor];
    [self addSubview:self.pageController.view];
}

-(void)configParam:(NSMutableArray<UIViewController *> *)controllers index:(NSInteger)index block:(TabSwitchBlcok)tabSwitch{
    if (controllers.count == 0) { return; }
    self.tabSwitch = tabSwitch;
    self.controllers = controllers;
    self.tabSwitch = tabSwitch;
    self.oriIndex = index;
    
    //默认展示的第index页面
    [self.pageController setViewControllers:[NSArray arrayWithObject:[self pageControllerAtIndex:index]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
}

/**
 更新滚动到index页面
 */
-(void)updateTab:(NSInteger)index{
    // 处理左右滚动方向
    UIPageViewControllerNavigationDirection direction = index > self.oriIndex ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse;
    [self.pageController setViewControllers:[NSArray arrayWithObject:[self pageControllerAtIndex:index]] direction:direction animated:YES completion:nil];
    self.oriIndex = index;
}

/** 返回下一个页面 */
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
    NSInteger index = [self.controllers indexOfObject:viewController];
    if(index == (self.controllers.count-1)){
        return nil;
    }
    index++;
    return [self pageControllerAtIndex:index];
}
/** 返回前一个页面 */
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
    NSInteger index = [self.controllers indexOfObject:viewController];
    if(index==0){
        return nil;
    }
    index--;
    return [self pageControllerAtIndex:index];
    
}
/** 创建内容页面 */
-(UIViewController*)pageControllerAtIndex:(NSInteger)index {
    if (index > self.controllers.count-1) {
        index = self.controllers.count - 1;
    }
    return [self.controllers objectAtIndex:index];
    
}
/** 结束滑动的时候触发 */
-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed{
    NSInteger index = [self.controllers indexOfObject:pageViewController.viewControllers[0]];
    self.tabSwitch(index);
}
/** 开始滑动的时候触发 */
-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers{
    
}

@end

第三步,使用

#import "LATabScrollView.h"
#import "LATabContentView.h"

@interface ViewController ()

@property (nonatomic, strong) LATabScrollView *tabScrollView;
@property (nonatomic, strong) LATabContentView *tabContent;

@end

@implementation ViewController

#define RandomColor ([UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1.0])

#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    CGFloat tabContentY = CGRectGetMaxY(self.tabScrollView.frame);
    self.tabContent.frame = CGRectMake(0, tabContentY, SCREEN_WIDTH, self.view.frame.size.height - tabContentY);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *navV = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 64)];
    navV.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:navV];
    
    
    NSArray *titles = @[@"海贼王",@"火影忍者",@"棋魂",@"名侦探柯南",@"今日头条",@"腾讯",@"阿里巴巴",@"百度"];
    self.tabScrollView = [[LATabScrollView alloc] init];
    [self.tabScrollView configParameterFrame:CGRectMake(0, CGRectGetMaxY(navV.frame), SCREEN_WIDTH, 50) titles:titles index:3 block:^(NSInteger index) {
        [self.tabContent updateTab:index];
    }];
    [self.view addSubview:self.tabScrollView];
    
    self.tabContent = [[LATabContentView alloc] init];
    [self.view addSubview:self.tabContent];
    
    NSMutableArray *contentM = [NSMutableArray array];
    for (NSInteger i = 0; i < titles.count; i++) {
        UIViewController *vc = [[UIViewController alloc] init];
        vc.view.backgroundColor = RandomColor;
        [contentM addObject:vc];
    }
    [self.tabContent configParam:contentM index:3 block:^(NSInteger index) {
        [self.tabScrollView tabOffset:index];
    }];
}

@end
上一篇 下一篇

猜你喜欢

热点阅读