IOS 之模拟网易新闻主页的滚动效果

原创 2014年05月15日 10:53:40

近下载了一个网易新闻的APP客户端,觉得新闻主页的滚动效果不错,每个标题都对应一个版面,如图


不好意思图有点大(是在网上下的,我就懒得截图了)

于是就模仿它写了一个demo程序.代码如下所示...

MainViewController是APP的主界面,负责初始化头部的scrollView以及底下的scrollView,在AppDelegate实现类中初始化该对象并设置根视图为它。


//  MainViewController.h  
//  test4101  
//  
//  Created by silicon on 14-4-10.  
//  Copyright (c) 2014年 silicon. All rights reserved.  
//  
  
#import <UIKit/UIKit.h>  
  
@interface MainViewController : UIViewController  
  
@end</pre><br>  
<br>   
  
<pre code_snippet_id="346326" snippet_file_name="blog_20140515_10_816282"></pre><pre code_snippet_id="346326" snippet_file_name="blog_20140515_29_2384508" name="code" class="objc"></pre><pre code_snippet_id="346326" snippet_file_name="blog_20140515_29_2384508" name="code" class="objc"></pre><pre code_snippet_id="346326" snippet_file_name="blog_20140515_29_2384508" name="code" class="objc"></pre><pre code_snippet_id="346326" snippet_file_name="blog_20140515_29_2384508" name="code" class="objc"></pre><pre code_snippet_id="346326" snippet_file_name="blog_20140515_13_2540906" name="code" class="objc">//  
//  MainViewController.m  
//  test4101  
//  
//  Created by silicon on 14-4-10.  
//  Copyright (c) 2014年 silicon. All rights reserved.  
//  
  
#import "MainViewController.h"  
#import "TopScrollView.h"  
#import "ButtomScrollView.h"  
  
@interface MainViewController ()  
  
@end  
  
@implementation MainViewController  
  
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
{  
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
    if (self) {  
        // Custom initialization  
    }  
    return self;  
}  
  
- (void)viewDidLoad  
{  
    [super viewDidLoad];  
    // Do any additional setup after loading the view from its nib.  
  
    UIImageView *topShadowImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 44, 320, 5)];  
    [topShadowImageView setImage:[UIImage imageNamed:@"top_background_shadow.png"]];  
    [self.view addSubview:topShadowImageView];  
      
    TopScrollView *topScrollView = [TopScrollView getInstance];  
    ButtomScrollView *buttomScrollView = [ButtomScrollView getInstance];  
      
    topScrollView.titleArray = @[@"苹果中国", @"iCloud", @"新浪微薄", @"维基百科", @"百度", @"中国雅虎", @"新闻", @"流行"];  
    buttomScrollView.viewNameArray = @[@"苹果中国", @"iCloud", @"新浪微薄", @"维基百科", @"百度", @"中国雅虎", @"新闻", @"流行"];  
      
    [self.view addSubview:topScrollView];  
    [self.view addSubview:buttomScrollView];  
      
    [topScrollView initWithTitleButtons];  
    [buttomScrollView initWithViews];  
}  
  
- (void)didReceiveMemoryWarning  
{  
    [super didReceiveMemoryWarning];  
    // Dispose of any resources that can be recreated.  
}  
  
@end

TopScrollView这个类主要用于控制上面标题的滚动逻辑,通过initWithTitleButtons这个函数来初始化按钮(包括按钮的标题,tag, 响应事件,坐标)并且将按钮的

x坐标以及宽度存储到容器中保存(相应读取可以按照控件的tag来取)。

selectNameButton用来控制按钮切换以及底部试图同步切换的逻辑。

adjustScrollViewContentX函数用于控制当按钮的x坐标超过了屏幕的最大宽时,调整按钮的x坐标至屏幕可见范围。

//  TopScrollView.h  
//  test4101  
//  
//  Created by silicon on 14-4-10.  
//  Copyright (c) 2014年 silicon. All rights reserved.  
//  
  
#import <UIKit/UIKit.h>  
  
@interface TopScrollView : UIScrollView <UIScrollViewDelegate>{  
    NSArray *titleArray;  
    NSInteger userSelectedButtonTag;  
    NSInteger scrollViewSelectedID;  
    UIImageView *shadowImage;  
}  
  
@property (nonatomic, retain) NSArray *titleArray;  
  
@property (nonatomic, retain) NSMutableArray *buttonWithArray;  
  
@property (nonatomic, retain) NSMutableArray *buttonOrignXArray;  
  
@property (assign) NSInteger scrollViewSelectedID;  
  
@property (assign) NSInteger userSelectedButtonTag;  
  
  
+ (TopScrollView *)getInstance;  
  
//加载顶部标题  
- (void)initWithTitleButtons;  
  
- (void)setButttonUnSelect;  
  
- (void)setButtonSelect;  
  
- (void)setScrollViewContentOffset;  
  
@end

//  TopScrollView.m  
//  test4101  
//  
//  Created by silicon on 14-4-10.  
//  Copyright (c) 2014年 silicon. All rights reserved.  
//  
  
#import "TopScrollView.h"  
#import "ButtomScrollView.h"  
  
@implementation TopScrollView  
@synthesize titleArray;  
@synthesize userSelectedButtonTag;  
@synthesize scrollViewSelectedID;  
@synthesize buttonOrignXArray;  
@synthesize buttonWithArray;  
  
+ (TopScrollView *)getInstance{  
    static TopScrollView *instance;  
    static dispatch_once_t onceToken;  
    dispatch_once(&onceToken, ^{  
        instance = [[self alloc] initWithFrame:CGRectMake(0, 20, CONTENTSIZEX, 44)];  
    });  
    return instance;  
}  
  
- (id)initWithFrame:(CGRect)frame  
{  
    self = [super initWithFrame:frame];  
    if (self) {  
        // Initialization code  
        self.delegate = self;  
        self.backgroundColor = [UIColor clearColor];  
        self.pagingEnabled = NO;  
        self.showsHorizontalScrollIndicator = NO;  
        self.showsVerticalScrollIndicator = NO;  
          
        userSelectedButtonTag = 100;  
        scrollViewSelectedID = 100;  
          
        self.buttonOrignXArray = [[NSMutableArray alloc] init];  
        self.buttonWithArray = [[NSMutableArray alloc] init];  
    }  
    return self;  
}  
  
- (void)initWithTitleButtons{  
      
    float xPos = 5.0f;  
    for(int i = 0; i < [self.titleArray count]; i++){  
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];  
        NSString *title = [self.titleArray objectAtIndex:i];  
        [button setTag:i + 100];  
        if(i == 0){  
            button.selected = YES;  
        }  
        [button setTitle:title forState:UIControlStateNormal];  
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
        [button addTarget:self action:@selector(selectNameButton:) forControlEvents:UIControlEventTouchUpInside];  
          
        int buttonWidth = [title sizeWithFont:button.titleLabel.font  
                            constrainedToSize:CGSizeMake(150, 30)  
                                lineBreakMode:NSLineBreakByClipping].width;  
      
        button.frame = CGRectMake(xPos, 9, buttonWidth + BUTTONGAP, 30);  
        [buttonOrignXArray addObject:@(xPos)];  
        //按钮的X坐标  
        xPos += buttonWidth + BUTTONGAP;  
        //按钮的宽度  
        [self.buttonWithArray addObject:@(button.frame.size.width)];  
        [self addSubview:button];  
    }  
    //视图的位移  
    self.contentSize = CGSizeMake(xPos, 44);  
    shadowImage = [[UIImageView alloc] initWithFrame:CGRectMake(BUTTONGAP, 0,  
                                                                [[self.buttonWithArray objectAtIndex:0] floatValue],  
                                                                44)];  
    [shadowImage setImage:[UIImage imageNamed:@"red_line_and_shadow.png"]];  
    [self addSubview:shadowImage];  
}  
  
- (void)selectNameButton:(UIButton *)sender{  
    [self adjustScrollViewContentX:sender];  
      
    //如果跟换按钮  
    if(sender.tag != userSelectedButtonTag){  
        UIButton *mybutton = (UIButton *)[self viewWithTag:userSelectedButtonTag];  
        mybutton.selected = NO;  
        userSelectedButtonTag = sender.tag;  
    }  
    //按钮选中状态  
    if(!sender.selected){  
        sender.selected = YES;  
        [UIView animateWithDuration:0.25 animations:^{  
            [shadowImage setFrame:CGRectMake(sender.frame.origin.x,  
                                             0,  
                                             [[self.buttonWithArray objectAtIndex:sender.tag - 100] floatValue],  
                                             44)];  
        } completion:^(BOOL finished) {  
            if(finished){  
                //页面出现  
                [[ButtomScrollView getInstance] setContentOffset:CGPointMake((sender.tag - 100) * 320, 0) animated:YES];  
                //滑动选择页面  
                scrollViewSelectedID = sender.tag;  
            }  
        }];  
    }  
}  
  
//调整滚动按钮显示  
- (void)adjustScrollViewContentX:(UIButton *)sender{  
    float originX = [[self.buttonOrignXArray objectAtIndex:(sender.tag - 100)] floatValue];  
    float width = [[self.buttonWithArray objectAtIndex:(sender.tag - 100)] floatValue];  
  
    if((sender.frame.origin.x - self.contentOffset.x) > (CONTENTSIZEX - (BUTTONGAP + width))){  
        [self setContentOffset:CGPointMake(originX - 30, 0) animated:YES];  
    }  
      
    if((sender.frame.origin.x - self.contentOffset.x) < 5){  
        [self setContentOffset:CGPointMake(originX, 0) animated:YES];  
    }  
}  
  
- (void)setButttonUnSelect{  
    UIButton *button = (UIButton *)[self viewWithTag:scrollViewSelectedID];  
    button.selected = NO;  
}  
  
- (void)setButtonSelect{  
    //选中滑动的按钮  
    UIButton *button = (UIButton *)[self viewWithTag:scrollViewSelectedID];  
    [UIView animateWithDuration:0.25 animations:^{  
        [shadowImage setFrame:CGRectMake(button.frame.origin.x, 0,  
                                         [[self.buttonWithArray objectAtIndex:button.tag - 100] floatValue],  
                                         44)];  
    } completion:^(BOOL finished) {  
        if(finished){  
            if(!button){  
                button.selected = YES;  
                userSelectedButtonTag = button.tag;  
            }  
        }  
    }];  
}  
  
- (void)setScrollViewContentOffset{  
    float originX = [[self.buttonOrignXArray objectAtIndex:(scrollViewSelectedID - 100)] floatValue];  
    float width = [[self.buttonWithArray objectAtIndex:(scrollViewSelectedID - 100)] floatValue];  
      
    if((originX - self.contentOffset.x) > (CONTENTSIZEX - (BUTTONGAP + width))){  
        [self setContentOffset:CGPointMake(originX - 30, 0) animated:YES];  
    }  
      
    if(originX - self.contentOffset.x < 5){  
        [self setContentOffset:CGPointMake(originX, 0) animated:YES];  
    }  
}  
  
@end

ButtomScrollView这个类主要控制底部视图的显示, adjustTopScrollViewButton函数用于调整按钮的显示,相关逻辑见源码(打字打的有点手酸)...

//  ButtomScrollView.h  
//  test4101  
//  
//  Created by silicon on 14-4-10.  
//  Copyright (c) 2014年 silicon. All rights reserved.  
//  
  
#import <UIKit/UIKit.h>  
  
@interface ButtomScrollView : UIScrollView<UIScrollViewDelegate>{  
    NSMutableArray *viewNameArray;  
    CGFloat userContentOffsetX;  
    BOOL isLeftScroll;  
}  
  
@property (nonatomic, retain) NSArray *viewNameArray;  
  
+ (ButtomScrollView *)getInstance;  
  
- (void)initWithViews;  
  
- (void)loadData;  
  
  
@end


//  ButtomScrollView.m  
//  test4101  
//  
//  Created by silicon on 14-4-10.  
//  Copyright (c) 2014年 silicon. All rights reserved.  
//  
  
#import "ButtomScrollView.h"  
#import "TopScrollView.h"  
  
  
@implementation ButtomScrollView  
@synthesize viewNameArray;  
  
- (id)initWithFrame:(CGRect)frame  
{  
    self = [super initWithFrame:frame];  
    if (self) {  
        // Initialization code  
        self.delegate = self;  
        self.backgroundColor = [UIColor lightGrayColor];  
        self.pagingEnabled = YES;  
        self.userInteractionEnabled = YES;  
        self.bounces = NO;  
      
        self.showsHorizontalScrollIndicator = NO;  
        self.showsVerticalScrollIndicator = NO;  
          
        userContentOffsetX = 0;  
    }  
    return self;  
}  
  
+ (ButtomScrollView *)getInstance{  
    static ButtomScrollView *instance;  
    static dispatch_once_t onceToken;  
    dispatch_once(&onceToken, ^{  
        instance = [[self alloc] initWithFrame:CGRectMake(0, 64, CONTENTSIZEX, 500)];  
    });  
    return instance;  
}  
  
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{  
    userContentOffsetX = scrollView.contentOffset.x;  
}  
  
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{  
    if(userContentOffsetX < scrollView.contentOffset.x){  
        isLeftScroll = YES;  
    }else{  
        isLeftScroll = NO;  
    }  
}  
  
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{  
    [self adjustTopScrollViewButton:scrollView];  
    [self loadData];  
}  
  
//调整按钮显示  
- (void)adjustTopScrollViewButton:(UIScrollView *)scrollView{  
    [[TopScrollView getInstance] setButttonUnSelect];  
    [TopScrollView getInstance].scrollViewSelectedID = POSITION + 100;  
    [[TopScrollView getInstance] setButtonSelect];  
    [[TopScrollView getInstance] setScrollViewContentOffset];  
}  
  
- (void)initWithViews{  
    for(int i = 0; i < [viewNameArray count]; i++){  
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50 + 320*i, 100, 320, self.frame.size.height - 44)];  
        label.tag = 200 + i;  
        if(i == 0){  
            label.text = [viewNameArray objectAtIndex:i];  
        }  
        [self addSubview:label];  
    }  
      
    self.contentSize = CGSizeMake(320*[viewNameArray count], self.frame.size.height - 44);  
}  
  
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView  
{  
    [self loadData];  
}  
  
- (void)loadData{  
    CGFloat pageWidth = self.frame.size.width;  
    int page = floor((self.contentOffset.x - pageWidth/viewNameArray.count)/pageWidth) + 1;  
    UILabel *label = (UILabel *)[self viewWithTag:page + 200];  
    label.text = [NSString stringWithFormat:@"%@", [viewNameArray objectAtIndex:page]];  
}

BTW,别忘了在Prefix文件中加入以下宏。

//  Prefix header  
//  
//  The contents of this file are implicitly included at the beginning of every source file.  
//  
  
#import <Availability.h>  
  
#ifndef __IPHONE_3_0  
#warning "This project uses features only available in iOS SDK 3.0 and later."  
#endif  
  
#define BUTTONGAP 10  
#define CONTENTSIZEX 320  
#define POSITION (int)(scrollView.contentOffset.x/320)  
  
#ifdef __OBJC__  
    #import <UIKit/UIKit.h>  
    #import <Foundation/Foundation.h>  
#endif

好了,以上就是该demo的源码,运行一下,如下图所以.



点击iCloud按钮,下面也随即切换到iCloud。



以上就是今天这篇文章所讲的全部内容了,希望大家指出问题,一起进步啊! 






版权声明:本文为博主原创文章,未经博主允许不得转载。

iOS滚动的导航条(仿网易新闻)

实现效果效果:选择不同的栏目,下面出现不同的视图,栏目条可以滚动;下面的视图也可以滚动,滚动时上面对应的栏目要选中颜色为红色; 实现代码 首先实现Main.storyboard 创建多个子控制器:头...
  • vbirdbest
  • vbirdbest
  • 2016年09月06日 14:30
  • 1587

iOS开发:仿网易新闻首页多频道视图切换

前言相信筒子们在项目中会遇到像网易新闻这样的多频道视图切换需求,而这一功能需要考虑的东西也挺多,其中最主要的就是内存问题了。 这种多频道视图切换一般分为两部分:上滚动视图(顶部频道列表)和下滚动视图(...
  • DaMingShen
  • DaMingShen
  • 2015年09月01日 10:55
  • 1833

模拟网易新闻主页的滚动效果

分类: IOS开发2014-05-15 10:53 4423人阅读 评论(4) 收藏 举报 ios开发新闻网易uiviewcontroller 最近下载了一个网易新闻的APP客户端...
  • zlyapple
  • zlyapple
  • 2015年09月11日 13:39
  • 285

iOS 模仿腾讯新闻首页,指示条及顶部滚动条效果

// // ViewController.m // 腾讯新闻模仿 // // Created by Eva on 2017/7/7. // Copyright © 2017年 shanghai...
  • qq_33380845
  • qq_33380845
  • 2017年07月18日 13:11
  • 124

Android之模拟网易新闻客户端

本实验主要是ListView解析json文件中的数据,需要Tomcat8.0来实现数据的动态更新。 首先把需要解析的json文件放置到Tomcat的webapp文件下的ROOT里面。 首...
  • wang520933
  • wang520933
  • 2017年05月23日 21:48
  • 81

iOS滚动的导航条(仿网易新闻)

实现效果效果:选择不同的栏目,下面出现不同的视图,栏目条可以滚动;下面的视图也可以滚动,滚动时上面对应的栏目要选中颜色为红色; 实现代码 首先实现Main.storyboard 创建多个子控制器:头...
  • vbirdbest
  • vbirdbest
  • 2016年09月06日 14:30
  • 1587

iOS网易新闻侧面抽屉交互效果

  • 2013年02月28日 15:31
  • 1.06MB
  • 下载

IOS抽屉效果简易实现,仿照网易新闻

  • 2014年02月23日 16:52
  • 235KB
  • 下载

ios模仿网易新闻首页效果

  • 2015年04月14日 15:36
  • 83KB
  • 下载

bootstrap实现视觉滚动差效果主页

  • 2017年05月12日 18:03
  • 2.89MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IOS 之模拟网易新闻主页的滚动效果
举报原因:
原因补充:

(最多只允许输入30个字)