仿网易新闻首页UI布局

作者: 袁俊亮技术博客 | 来源:发表于2016-04-14 15:20 被阅读929次

    title : 仿网易新闻首页UI布局
    category : UI


    仿网易新闻首页UI布局

    标签(空格分隔): UI


    [TOC]

    源码下载

    链接: http://pan.baidu.com/s/1sliRak1 密码: 89jn

    效果图(通过Storyboard+代码的方式实现)

    仿网易新闻首页UI效果图.png

    实现代码

    JLHomeViewController

    继承自UIViewController,主要文件,负责整个效果的逻辑和实现

    
    #import "JLHomeViewController.h"
    #import "JLTestViewController.h"
    #import "JLHomeLabel.h"
    #import "JLConst.h"
    
    @interface JLHomeViewController ()<UIScrollViewDelegate>
    /** 标题 */
    @property (weak, nonatomic) IBOutlet UIScrollView *titleScrollView;
    /** 内容 */
    @property (weak, nonatomic) IBOutlet UIScrollView *contentScrollView;
    
    @end
    
    @implementation JLHomeViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.automaticallyAdjustsScrollViewInsets = NO;
        
        // 添加标题
        [self setupChildVc];
        
        // 添加子控制器
        [self setupTitle];
        
        // 默认显示第0个子控制器的
        [self scrollViewDidEndScrollingAnimation:self.contentScrollView];
    }
    
    #pragma mark - 初始化
    
    /**
     *  添加标题
     */
    - (void)setupTitle
    {
        CGFloat labelW = 100;
        CGFloat labelY = 0;
        CGFloat labelH = self.titleScrollView.frame.size.height;
        for (int i = 0; i < 7; i++) {
            JLHomeLabel *label = [[JLHomeLabel alloc] init];
            CGFloat labelX = labelW * i;
            label.frame = CGRectMake(labelX, labelY, labelW, labelH);
            label.text = [self.childViewControllers[i] title];
            // 给label添加手势监听事件
            [label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick:)]];
            
            // 给label绑定tag
            label.tag = i;
            [self.titleScrollView addSubview:label];
            
            if (i == 0) {
                label.scale = 1.0;
            }
        }
        
        // 设置titleScrollView的contentSize
        self.titleScrollView.contentSize = CGSizeMake(labelW * 7, 0);
        // 设置contentScrollView的contentSize
        // 注意这里的width要用屏幕的宽度,因为这时候加载出来的self.contentScrollView.frame.size.width是XIB的初始宽度600.
        // 由于self.view.autoresizingMask的原因使得控制器的view的宽度随着父控制器的frame的改变而改变。所以显示出来以后,self.contentScrollView.frame.size.width为正常的屏幕的宽度
        self.contentScrollView.contentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width * 7, 0);
    }
    
    
    /**
     *  添加子控制器
     */
    - (void)setupChildVc
    {
        JLTestViewController *testVc0 = [[JLTestViewController alloc] init];
        testVc0.title = @"国际";
        [self addChildViewController:testVc0];
        
        JLTestViewController *testVc1 = [[JLTestViewController alloc] init];
        testVc1.title = @"军事";
        [self addChildViewController:testVc1];
        
        JLTestViewController *testVc2 = [[JLTestViewController alloc] init];
        testVc2.title = @"社会";
        [self addChildViewController:testVc2];
        
        JLTestViewController *testVc3 = [[JLTestViewController alloc] init];
        testVc3.title = @"政治";
        [self addChildViewController:testVc3];
        
        JLTestViewController *testVc4 = [[JLTestViewController alloc] init];
        testVc4.title = @"经济";
        [self addChildViewController:testVc4];
        
        JLTestViewController *testVc5 = [[JLTestViewController alloc] init];
        testVc5.title = @"体育";
        [self addChildViewController:testVc5];
        
        JLTestViewController *testVc6 = [[JLTestViewController alloc] init];
        testVc6.title = @"娱乐";
        [self addChildViewController:testVc6];
    }
    
    #pragma mark - 手势监听事件
    /**
     *  label被点击以后调用
     *
     *  @param tap 手势
     */
    - (void)labelClick:(UIGestureRecognizer *)tap
    {
        // 取出被点击的label的索引
        NSInteger index = tap.view.tag;
        
        // 让底部的内容scrollView滚动到对应的位置
        CGPoint offset = self.contentScrollView.contentOffset;
        offset.x = self.contentScrollView.frame.size.width * index;
        [self.contentScrollView setContentOffset:offset animated:YES];
    }
    
    #pragma mark - <UIScrollViewDelegate>
    /**
     *  当scrollView结束了滚动动画以后就会调用这个方法
     *
     *  @param scrollView 当前滚动的scrollView
     */
    - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
    {
        CGFloat scrollViewW = scrollView.frame.size.width;
        CGFloat scrollViewH = scrollView.frame.size.height;
        CGFloat offsetX = scrollView.contentOffset.x;
        
        // 当前位置需要显示的控制器的索引
        NSInteger index = offsetX / scrollViewW;
        
        // 让对应的顶部标题居中显示
        JLHomeLabel *label = self.titleScrollView.subviews[index];
        CGPoint titleOffset = self.titleScrollView.contentOffset;
        titleOffset.x = label.center.x - scrollViewW * 0.5;
        
        // 左边超出处理
        if (titleOffset.x < 0) titleOffset.x = 0;
        // 右边超出处理
        CGFloat maxTitleOffsetX = self.titleScrollView.contentSize.width - scrollViewW;
        if (titleOffset.x > maxTitleOffsetX) titleOffset.x = maxTitleOffsetX;
        
        [self.titleScrollView setContentOffset:titleOffset animated:YES];
        
        // 让其他label回到最初的状态
        for (JLHomeLabel *otherLabel in self.titleScrollView.subviews) {
            if (otherLabel != label) otherLabel.scale = 0.0;
        }
    
        // 取出需要显示的控制器
        UIViewController *willShowVc = self.childViewControllers[index];
        
        // 如果当前位置的控制器的view已经显示过了,就直接返回
        if ([willShowVc isViewLoaded]) return;
        
        // 添加控制器的view到contentScrollView中
        willShowVc.view.frame = CGRectMake(offsetX, 0, scrollViewW, scrollViewH);
        [self.contentScrollView addSubview:willShowVc.view];
    
    }
    
    // 手动拖动scrollView松开后停止减速完毕后才会调用这个方法
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
        [self scrollViewDidEndScrollingAnimation:scrollView];
    }
    
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        // 获取比例值
        CGFloat scale = scrollView.contentOffset.x / scrollView.frame.size.width;
        if (scale < 0 || scale > (self.titleScrollView.subviews.count - 1)) return;
        
        // 获得需要操作的左边label
        NSInteger leftIndex = scale;
        JLHomeLabel *leftLabel = self.titleScrollView.subviews[leftIndex];
        
        // 获得需要操作的右边的label
        NSInteger rightIndex = leftIndex + 1;
        JLHomeLabel *rightLabel = (rightIndex == self.titleScrollView.subviews.count) ? nil : self.titleScrollView.subviews[rightIndex];
        
        // 右边比例
        CGFloat rightScale = scale - leftIndex;
        // 左边比例
        CGFloat leftScale = 1 - rightScale;
        
        // 设置label的比例
        leftLabel.scale = leftScale;
        rightLabel.scale = rightScale;
    }
    
    @end
    
    

    JLTestViewController

    继承自UITableViewController,测试文件,用于颜色内容控制器样式

    .m文件

    
    #import "JLTestViewController.h"
    
    @interface JLTestViewController ()
    
    @end
    static NSString *ID = @"testCell";
    
    @implementation JLTestViewController
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 注册cell
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
        return 50;
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
       
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        
        cell.textLabel.text = [NSString stringWithFormat:@"%@ --- %zd",self.title, indexPath.row];
        
        return cell;
    }
    
    @end
    
    

    JLHomeLabel

    继承自UILabel,自定义的label,对UILabel的一个简单封装

    .h文件

    #import <UIKit/UIKit.h>
    
    @interface JLHomeLabel : UILabel
    
    /** label的缩放比例 */
    @property (nonatomic, assign) CGFloat scale;
    
    @end
    

    .m文件

    
    #import "JLHomeLabel.h"
    #import "JLConst.h"
    
    @implementation JLHomeLabel
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            self.font = [UIFont systemFontOfSize:15];
            self.textColor = [UIColor colorWithRed:JLRed green:JLGreen blue:JLBlue alpha:JLAlpha];
            self.textAlignment = NSTextAlignmentCenter;
            // 使label和用户之间可交互
            self.userInteractionEnabled = YES;
        }
        return self;
    }
    
    - (void)setScale:(CGFloat)scale
    {
        CGFloat red = JLRed + (1 - JLRed) * scale;
        CGFloat green = JLGreen + (0 - JLGreen) * scale;
        CGFloat blue = JLBlue + (0 - JLBlue) * scale;
        self.textColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
        
        // 大小缩放比例
        CGFloat transformScale = 1 + scale * 0.2;
        self.transform = CGAffineTransformMakeScale(transformScale, transformScale);
    }
    
    @end
    
    

    JLConst

    用于存放全局的常量

    .h文件

    #import <UIKit/UIKit.h>
    
    UIKIT_EXTERN const CGFloat JLRed;
    UIKIT_EXTERN const CGFloat JLGreen;
    UIKIT_EXTERN const CGFloat JLBlue;
    UIKIT_EXTERN const CGFloat JLAlpha;
    
    

    .m文件

    #import <UIKit/UIKit.h>
    
    const CGFloat JLRed = 0;
    const CGFloat JLGreen = 0;
    const CGFloat JLBlue = 0;
    const CGFloat JLAlpha = 1.0;
    
    

    相关文章

      网友评论

      本文标题:仿网易新闻首页UI布局

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