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