zoukankan      html  css  js  c++  java
  • 实战项目-网易

    重点:ContentOffset偏移量计算

    判断防止View视图重复加载

     UIViewController * vc = self.childViewControllers[i];
        //FIXME:防止重复加载View视图
        if (vc.viewIfLoaded) {
            //iOS 9.0之后
            return;
        }
        //FIXME:通用
        if (vc.view.superview) {
            return;
        }

    代码:(未抽取)

    #import "ViewController.h"
    #import "TopLineViewController.h"
    #import "HotViewController.h"
    #import "VideoViewController.h"
    #import "ScienceViewController.h"
    #import "SocietyViewController.h"
    #import "ReaderViewController.h"
    #define ScreenW [[UIScreen mainScreen] bounds].size.width
    #define ScreenH [[UIScreen mainScreen] bounds].size.height
    @interface ViewController ()<UIScrollViewDelegate>
    /** 标题按钮数组 */
    @property (nonatomic, strong) NSMutableArray * titleBtns ;
    /** 上一次选中的按钮 */
    @property (nonatomic, strong) UIButton * selectedBtn ;
    @property (nonatomic, weak) UIScrollView *titleScrollView;
    @property (nonatomic, weak) UIScrollView *contentScrollView;
    
    @end
    
    @implementation ViewController
    -(NSMutableArray *)titleBtns {
        if (!_titleBtns) {
            _titleBtns = @[].mutableCopy;
        }
        return _titleBtns;
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.navigationItem.title = @"网易新闻";
        
        // 1.添加标题滚动视图
        [self setupTitleScrollView];
        
        // 2.添加内容滚动视图
        [self setupContentScrollView];
        
        //3.添加所有的子控制器
        [self setupAllChildViewController];
        
        //4.设置所有的标题
        [self setupAllTitles];
        
        //5.处理标题的点击
        
        //7.FIXME:scrollView的额外滚动区域64
        //iOS 7以后,导航控制器中scrollView顶部会添加64的额外滚动区域
        self.automaticallyAdjustsScrollViewInsets = NO;
        
    }
    #pragma mark - 设置所有的标题
    - (void)setupAllTitles {
        //已经把我们想要的内容展示上去 -> 展示的效果是否是我们想要的(调整细节)
        //1.标题的颜色 为黑色
        //2.需要让titleScrollView可以滚动
        //添加所有标题按钮
        NSInteger count = self.childViewControllers.count;
        CGFloat btnW = 100;
        CGFloat btnH = self.titleScrollView.bounds.size.height;
        CGFloat btnX = 0;
        for (NSInteger i = 0; i<count; i++) {
            UIButton *titleBtn = [UIButton buttonWithType:UIButtonTypeCustom];
            titleBtn.tag = i;
            //设置标题
            UIViewController * vc = self.childViewControllers[i];
            [titleBtn setTitle:vc.title forState:UIControlStateNormal];
            //设置Frame
            btnX = i * btnW;
            titleBtn.frame = CGRectMake(btnX, 0, btnW, btnH);
            [titleBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            //监听按钮点击
            [titleBtn addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside];
            //设置第一个按钮默认选中(头条默认选中)
            if (i == 0) {
                [self titleClick:titleBtn];
            }
            //把标题按钮保存到对应的数组中
            [self.titleBtns addObject:titleBtn];
            [self.titleScrollView addSubview:titleBtn];
        }
        
        //设置标题滚动范围
        self.titleScrollView.contentSize = CGSizeMake(count * btnW, 0);
        self.titleScrollView.showsHorizontalScrollIndicator = NO;
        
        //6.设置内容的滚动范围
        self.contentScrollView.contentSize = CGSizeMake(count * ScreenW, 0);
        //bug:代码跟我的一样,但是标题显示不出来
        //bug: 内容往下移动,莫名其妙
        //FIXME:9.选中标题居中处理->选中标题
        //10.标题文字缩放
    }
    
    #pragma mark - 选中标题
    - (void)selButton:(UIButton*)button {
        _selectedBtn.transform = CGAffineTransformIdentity;
        [_selectedBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        //_selectedBtn = button;
        //标题居中处理
        [self setupTitleCenter:button];
        //字体缩放: 形变
        button.transform = CGAffineTransformMakeScale(1.3, 1.3);
        _selectedBtn = button;
        [self setupTitleScale];
    }
    #pragma mark - 字体缩放
    - (void)setupTitleScale {
        
    }
    #pragma mark - 标题居中处理
    - (void)setupTitleCenter:(UIButton*)button {
        //本质:修改titleScrollView的偏移量
        CGFloat offsetX = button.center.x - ScreenW * 0.5;
        NSLog(@"offsetX==%f",offsetX);
        //头条、热点(offsetX<0)
        if (offsetX < 0) {
            offsetX = 0;
        }
        //最大偏移量计算(解决订阅和科技)
         CGFloat maxOffsetX = self.titleScrollView.contentSize.width - ScreenW;
        if (offsetX > maxOffsetX) {
            offsetX = maxOffsetX;
        }
        [self.titleScrollView setContentOffset: CGPointMake(offsetX, 0) animated:YES];
        //此时有bug:点击每个按钮都居中了,例如:头条、热点(offsetX<0)
    }
    
    #pragma mark - 添加一个子控制器的View
    - (void)setupOneViewController:(NSInteger)i {
        UIViewController * vc = self.childViewControllers[i];
        //FIXME:防止重复加载View视图
    //    if (vc.viewIfLoaded) {
    //        //iOS 9.0之后
    //        return;
    //    }
        //FIXME:通用
        if (vc.view.superview) {
            return;
        }
        CGFloat x = i * ScreenW;
        vc.view.frame = CGRectMake(x, 0, ScreenW, self.contentScrollView.bounds.size.height);
        [self.contentScrollView addSubview:vc.view];
    }
    #pragma mark - 处理标题点击
    - (void)titleClick:(UIButton*)button {
        //FIXME:8.监听内容视图滚动
        NSInteger i = button.tag;
        //1.标题颜色变为红色
        [self selButton:button];
        //2.把对应子控制器的View添加上去
        [self setupOneViewController:i];
        //3.滚动到对应的位置
        self.contentScrollView.contentOffset = CGPointMake(i * ScreenW, 0);
    }
    #pragma mark - 添加所有子控制器
    - (void)setupAllChildViewController {
        
        //头条
        TopLineViewController * vc = [TopLineViewController new];
        vc.title = @"头条";
        [self addChildViewController:vc];
        //热点
        HotViewController * hotVC = [HotViewController new];
        hotVC.title = @"热点";
        [self addChildViewController:hotVC];
        //视频
        VideoViewController * videoVC = [VideoViewController new];
        videoVC.title = @"视频";
        [self addChildViewController:videoVC];
        //社会
        SocietyViewController * societyVC = [SocietyViewController new];
        societyVC.title = @"社会";
        [self addChildViewController:societyVC];
        //订阅
        ReaderViewController * readerVC = [ReaderViewController new];
        readerVC.title = @"订阅";
        [self addChildViewController:readerVC];
        //科技
        ScienceViewController * scienceVC = [ScienceViewController new];
        scienceVC.title = @"科技";
        [self addChildViewController:scienceVC];
        
    }
    #pragma mark - 添加标题滚动视图
    - (void)setupTitleScrollView
    {
        // 创建titleScrollView
        UIScrollView *titleScrollView = [[UIScrollView alloc] init];
        //titleScrollView.backgroundColor = [UIColor redColor];
        CGFloat y = self.navigationController.navigationBarHidden ? 20 : 64;
        titleScrollView.frame = CGRectMake(0, y, self.view.bounds.size.width, 44);
        [self.view addSubview:titleScrollView];
        _titleScrollView = titleScrollView;
        
    }
    
    #pragma mark - 添加内容滚动视图
    - (void)setupContentScrollView
    {
        // 创建contentScrollView
        UIScrollView *contentScrollView = [[UIScrollView alloc] init];
        contentScrollView.backgroundColor = [UIColor greenColor];
        CGFloat y = CGRectGetMaxY(self.titleScrollView.frame);
        contentScrollView.frame = CGRectMake(0, y, self.view.bounds.size.width, self.view.bounds.size.height - y);
        [self.view addSubview:contentScrollView];
        _contentScrollView = contentScrollView;
        //设置contentScrollView的属性
        // 分页
        self.contentScrollView.pagingEnabled = YES;
        // 弹簧
        self.contentScrollView.bounces = NO;
        // 指示器
        self.contentScrollView.showsHorizontalScrollIndicator = NO;
        //设置代理.目的:监听内容滚动视图 什么时候滚动完成
        self.contentScrollView.delegate = self;
        
    }
    #pragma mark - UIScrollViewDelegate
    #pragma mark - 滚动完成的时候调用
    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        
        //获取当前的角标
        NSInteger i =  scrollView.contentOffset.x / ScreenW;//偏移量/屏幕宽度
        
        //获取标题按钮
        UIButton *titleBtn = self.titleBtns[i];
        
        //1.选中标题
        [self selButton:titleBtn];
        //2.把对应子控制器的view添加上去
        [self setupOneViewController:i];
        
    }
    #pragma mark - 只要一滚动就需要字体渐变
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        
        //字体缩放  1.缩放比例 2.缩放哪两个按钮
        NSInteger page = scrollView.contentOffset.x / ScreenW;
        NSLog(@"%ld",page);
        NSInteger leftI = scrollView.contentOffset.x / ScreenW;
        NSInteger rightI = leftI + 1;
        // 获取左边的按钮
        UIButton * leftBtn = self.titleBtns[leftI];
        NSInteger count = self.titleBtns.count;
        
        // 获取右边的按钮
        UIButton * rightBtn;
        if (rightI < count) {
            rightBtn = self.titleBtns[rightI];
        }
        // 0~1 => 1~1.3
        CGFloat scaleR = scrollView.contentOffset.x / ScreenW;
        scaleR -= leftI;
        
        CGFloat scaleL = 1- scaleR;
        NSLog(@"%f",scaleR);
        //缩放按钮
        leftBtn.transform = CGAffineTransformMakeScale(scaleL * 0.3+1, scaleL * 0.3+1);
        rightBtn.transform = CGAffineTransformMakeScale(scaleR * 0.3+1, scaleR * 0.3+1);
        
        //FIXME:颜色渐变
        //黑色变成红色
        UIColor * rightColor = [UIColor colorWithRed:scaleR green:0 blue:0 alpha:1];
        UIColor * leftColor = [UIColor colorWithRed:scaleL green:0 blue:0 alpha:1];
        [rightBtn setTitleColor:rightColor forState:UIControlStateNormal];
        [leftBtn setTitleColor:leftColor forState:UIControlStateNormal];
        
    }
    /*
     颜色:3种颜色通道组成: R:红 G 绿 B: k蓝
     白色: 1 1 1
     黑色: 0 0 0
     红色: 1 0 0
     */

     代码:(已抽取)

    BaseVC:

    #import "ViewController.h"
    #define ScreenW [[UIScreen mainScreen] bounds].size.width
    #define ScreenH [[UIScreen mainScreen] bounds].size.height
    @interface ViewController ()<UIScrollViewDelegate>
    /** 标题按钮数组 */
    @property (nonatomic, strong) NSMutableArray * titleBtns ;
    /** 上一次选中的按钮 */
    @property (nonatomic, strong) UIButton * selectedBtn ;
    @property (nonatomic, weak) UIScrollView *titleScrollView;
    @property (nonatomic, weak) UIScrollView *contentScrollView;
    /** 判断是否初始化 */
    @property (nonatomic, assign) BOOL isInitialize;
    @end
    
    @implementation ViewController
    -(void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        if (_isInitialize == NO) {
            //4.设置所有的标题
            [self setupAllTitles];
            _isInitialize = YES;
        }
    }
    -(NSMutableArray *)titleBtns {
        if (!_titleBtns) {
            _titleBtns = @[].mutableCopy;
        }
        return _titleBtns;
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.navigationItem.title = @"网易新闻";
        // 1.添加标题滚动视图
        [self setupTitleScrollView];
        
        // 2.添加内容滚动视图
        [self setupContentScrollView];
        //5.处理标题的点击
        
        //7.FIXME:scrollView的额外滚动区域64
        //iOS 7以后,导航控制器中scrollView顶部会添加64的额外滚动区域
        self.automaticallyAdjustsScrollViewInsets = NO;
    }
    #pragma mark - 设置所有的标题
    - (void)setupAllTitles {
        //已经把我们想要的内容展示上去 -> 展示的效果是否是我们想要的(调整细节)
        //1.标题的颜色 为黑色
        //2.需要让titleScrollView可以滚动
        //添加所有标题按钮
        NSInteger count = self.childViewControllers.count;
        CGFloat btnW = 100;
        CGFloat btnH = self.titleScrollView.bounds.size.height;
        CGFloat btnX = 0;
        for (NSInteger i = 0; i<count; i++) {
            UIButton *titleBtn = [UIButton buttonWithType:UIButtonTypeCustom];
            titleBtn.tag = i;
            //设置标题
            UIViewController * vc = self.childViewControllers[i];
            [titleBtn setTitle:vc.title forState:UIControlStateNormal];
            //设置Frame
            btnX = i * btnW;
            titleBtn.frame = CGRectMake(btnX, 0, btnW, btnH);
            [titleBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            //监听按钮点击
            [titleBtn addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside];
            //设置第一个按钮默认选中(头条默认选中)
            if (i == 0) {
                [self titleClick:titleBtn];
            }
            //把标题按钮保存到对应的数组中
            [self.titleBtns addObject:titleBtn];
            [self.titleScrollView addSubview:titleBtn];
        }
        //设置标题滚动范围
        self.titleScrollView.contentSize = CGSizeMake(count * btnW, 0);
        self.titleScrollView.showsHorizontalScrollIndicator = NO;
        //6.设置内容的滚动范围
        self.contentScrollView.contentSize = CGSizeMake(count * ScreenW, 0);
    }
    
    #pragma mark - 选中标题
    - (void)selButton:(UIButton*)button {
        _selectedBtn.transform = CGAffineTransformIdentity;
        [_selectedBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        //_selectedBtn = button;
        //标题居中处理
        [self setupTitleCenter:button];
        //字体缩放: 形变
        button.transform = CGAffineTransformMakeScale(1.3, 1.3);
        _selectedBtn = button;
        [self setupTitleScale];
    }
    #pragma mark - 字体缩放
    - (void)setupTitleScale {
        
    }
    #pragma mark - 标题居中处理
    - (void)setupTitleCenter:(UIButton*)button {
        //本质:修改titleScrollView的偏移量
        CGFloat offsetX = button.center.x - ScreenW * 0.5;
        NSLog(@"offsetX==%f",offsetX);
        //头条、热点(offsetX<0)
        if (offsetX < 0) {
            offsetX = 0;
        }
        //最大偏移量计算(解决订阅和科技)
         CGFloat maxOffsetX = self.titleScrollView.contentSize.width - ScreenW;
        if (offsetX > maxOffsetX) {
            offsetX = maxOffsetX;
        }
        [self.titleScrollView setContentOffset: CGPointMake(offsetX, 0) animated:YES];
        //此时有bug:点击每个按钮都居中了,例如:头条、热点(offsetX<0)
    }
    
    #pragma mark - 添加一个子控制器的View
    - (void)setupOneViewController:(NSInteger)i {
        UIViewController * vc = self.childViewControllers[i];
        //FIXME:防止重复加载View视图
    //    if (vc.viewIfLoaded) {
    //        //iOS 9.0之后
    //        return;
    //    }
        //FIXME:通用
        if (vc.view.superview) {
            return;
        }
        CGFloat x = i * ScreenW;
        vc.view.frame = CGRectMake(x, 0, ScreenW, self.contentScrollView.bounds.size.height);
        [self.contentScrollView addSubview:vc.view];
    }
    #pragma mark - 处理标题点击
    - (void)titleClick:(UIButton*)button {
        //FIXME:8.监听内容视图滚动
        NSInteger i = button.tag;
        //1.标题颜色变为红色
        [self selButton:button];
        //2.把对应子控制器的View添加上去
        [self setupOneViewController:i];
        //3.滚动到对应的位置
        self.contentScrollView.contentOffset = CGPointMake(i * ScreenW, 0);
    }
    #pragma mark - 添加标题滚动视图
    - (void)setupTitleScrollView
    {
        // 创建titleScrollView
        UIScrollView *titleScrollView = [[UIScrollView alloc] init];
        //titleScrollView.backgroundColor = [UIColor redColor];
        CGFloat y = self.navigationController.navigationBarHidden ? 20 : 64;
        titleScrollView.frame = CGRectMake(0, y, self.view.bounds.size.width, 44);
        [self.view addSubview:titleScrollView];
        _titleScrollView = titleScrollView;
        
    }
    
    #pragma mark - 添加内容滚动视图
    - (void)setupContentScrollView
    {
        // 创建contentScrollView
        UIScrollView *contentScrollView = [[UIScrollView alloc] init];
        contentScrollView.backgroundColor = [UIColor greenColor];
        CGFloat y = CGRectGetMaxY(self.titleScrollView.frame);
        contentScrollView.frame = CGRectMake(0, y, self.view.bounds.size.width, self.view.bounds.size.height - y);
        [self.view addSubview:contentScrollView];
        _contentScrollView = contentScrollView;
        //设置contentScrollView的属性
        // 分页
        self.contentScrollView.pagingEnabled = YES;
        // 弹簧
        self.contentScrollView.bounces = NO;
        // 指示器
        self.contentScrollView.showsHorizontalScrollIndicator = NO;
        //设置代理.目的:监听内容滚动视图 什么时候滚动完成
        self.contentScrollView.delegate = self;
        
    }
    #pragma mark - UIScrollViewDelegate
    #pragma mark - 滚动完成的时候调用
    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        
        //获取当前的角标
        NSInteger i =  scrollView.contentOffset.x / ScreenW;//偏移量/屏幕宽度
        
        //获取标题按钮
        UIButton *titleBtn = self.titleBtns[i];
        
        //1.选中标题
        [self selButton:titleBtn];
        //2.把对应子控制器的view添加上去
        [self setupOneViewController:i];
        
    }
    #pragma mark - 只要一滚动就需要字体渐变
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        
        //字体缩放  1.缩放比例 2.缩放哪两个按钮
        NSInteger page = scrollView.contentOffset.x / ScreenW;
        NSLog(@"%ld",page);
        NSInteger leftI = scrollView.contentOffset.x / ScreenW;
        NSInteger rightI = leftI + 1;
        // 获取左边的按钮
        UIButton * leftBtn = self.titleBtns[leftI];
        NSInteger count = self.titleBtns.count;
        
        // 获取右边的按钮
        UIButton * rightBtn;
        if (rightI < count) {
            rightBtn = self.titleBtns[rightI];
        }
        // 0~1 => 1~1.3
        CGFloat scaleR = scrollView.contentOffset.x / ScreenW;
        scaleR -= leftI;
        
        CGFloat scaleL = 1- scaleR;
        NSLog(@"%f",scaleR);
        //缩放按钮
        leftBtn.transform = CGAffineTransformMakeScale(scaleL * 0.3+1, scaleL * 0.3+1);
        rightBtn.transform = CGAffineTransformMakeScale(scaleR * 0.3+1, scaleR * 0.3+1);
        
        //FIXME:颜色渐变
        //黑色变成红色
        UIColor * rightColor = [UIColor colorWithRed:scaleR green:0 blue:0 alpha:1];
        UIColor * leftColor = [UIColor colorWithRed:scaleL green:0 blue:0 alpha:1];
        [rightBtn setTitleColor:rightColor forState:UIControlStateNormal];
        [leftBtn setTitleColor:leftColor forState:UIControlStateNormal];
        
    }

    网易VC

    #import <UIKit/UIKit.h>
    #import "ViewController.h"
    NS_ASSUME_NONNULL_BEGIN
    @interface HKWYViewController : ViewController
    @end
    NS_ASSUME_NONNULL_END
    
    #import "HKWYViewController.h"
    #import "TopLineViewController.h"
    #import "HotViewController.h"
    #import "VideoViewController.h"
    #import "ScienceViewController.h"
    #import "SocietyViewController.h"
    #import "ReaderViewController.h"
    @interface HKWYViewController ()
    
    @end
    
    @implementation HKWYViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //3.添加所有的子控制器
        [self setupAllChildViewController];
        
    }
    #pragma mark - 添加所有子控制器
    - (void)setupAllChildViewController {
        
        //头条
        TopLineViewController * vc = [TopLineViewController new];
        vc.title = @"头条";
        [self addChildViewController:vc];
        //热点
        HotViewController * hotVC = [HotViewController new];
        hotVC.title = @"热点";
        [self addChildViewController:hotVC];
        //视频
        VideoViewController * videoVC = [VideoViewController new];
        videoVC.title = @"视频";
        [self addChildViewController:videoVC];
        //社会
        SocietyViewController * societyVC = [SocietyViewController new];
        societyVC.title = @"社会";
        [self addChildViewController:societyVC];
        //订阅
        ReaderViewController * readerVC = [ReaderViewController new];
        readerVC.title = @"订阅";
        [self addChildViewController:readerVC];
        //科技
        ScienceViewController * scienceVC = [ScienceViewController new];
        scienceVC.title = @"科技";
        [self addChildViewController:scienceVC];
        
    }
  • 相关阅读:
    prototype.js超强的javascript类库
    MySQL Server Architecture
    Know more about RBA redo block address
    MySQL无处不在
    利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
    LAMP Stack
    9i中DG remote archive可能导致Primary Database挂起
    Oracle数据库升级与补丁
    Oracle为何会发生归档日志archivelog大小远小于联机重做日志online redo log size的情况?
    Oracle Ksplice如何工作?How does Ksplice work?
  • 原文地址:https://www.cnblogs.com/StevenHuSir/p/10037622.html
Copyright © 2011-2022 走看看