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

近下载了一个网易新闻的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。



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






阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shenjie12345678/article/details/25875163
个人分类: IOS开发
上一篇设计模式之工厂模式
下一篇IOS开发之瀑布流照片墙实现
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭