最近下载了一个网易新闻的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。
以上就是今天这篇文章所讲的全部内容了,希望大家指出问题,一起进步啊!