美文网首页
iOS 利用UIScrollView和UIPageViewCon

iOS 利用UIScrollView和UIPageViewCon

作者: HCL黄 | 来源:发表于2019-10-23 14:43 被阅读0次
    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
    

    相关文章

      网友评论

          本文标题:iOS 利用UIScrollView和UIPageViewCon

          本文链接:https://www.haomeiwen.com/subject/uhahvctx.html