IOS UIScrollView + UIButton 实现页面和顶部标签页水平滚动效果

  很长一段时间没有写博客了,最近在学习iOS开发,看了不少的代码,自己用UIScrollView和UIButton实现了水平滚动的效果,有点类似于今日头条的主界面框架,效果如下:

代码如下:

MyScrollView.h

#import <UIKit/UIKit.h>
#import "MySegementView.h"

@interface MyScrollView : UIView<UIScrollViewDelegate>

- (instancetype) initWithFrame:(CGRect)frame titleArray:(NSArray *)titleArray viewArray:(NSArray *)viewArray;

//滚动页面
@property (strong, nonatomic)UIScrollView *myScrollView;

//顶部标签按钮滚动视图
@property (strong, nonatomic)MySegementView *mySegementView;

@end

MyScrollView.m

#define SCROLLVIEW_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCROLLVIEW_HEIGTH self.bounds.size.height
#define SEGEMENT_HEIGTHT 44

#import "MyScrollView.h"

@implementation MyScrollView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

- (instancetype) initWithFrame:(CGRect)frame titleArray:(NSArray *)titleArray viewArray:(NSArray *)viewArray
{
    self = [super initWithFrame:frame];
    if (_mySegementView == nil) {
        _mySegementView = [[MySegementView alloc] initWithFrame:CGRectMake(0, 0, SCROLLVIEW_WIDTH, SEGEMENT_HEIGTHT) titleArray:titleArray block:^void(int index){  //用block实现回调,顶部按钮点击的时候滚动到指定位置
            [_myScrollView setContentOffset:CGPointMake((index - 1) * SCROLLVIEW_WIDTH, 0)];
        }];
    }
    [self addSubview:_mySegementView];
    [self addSubview:self.myScrollView];

    if (self) {
        for (int i = 0; i < viewArray.count; i++) {
            UIViewController *viewController = viewArray[i];
            viewController.view.frame = CGRectMake(i * SCROLLVIEW_WIDTH, 0, SCROLLVIEW_WIDTH, self.myScrollView.frame.size.height);
            [self.myScrollView addSubview:viewController.view];
        }
        self.myScrollView.contentSize = CGSizeMake(viewArray.count * SCROLLVIEW_WIDTH, 0);
    }

    return self;
}

// 滚动页面视图懒加载
- (UIScrollView *)myScrollView
{
    if (_myScrollView == nil) {
        _myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, _mySegementView.frame.size.height, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGTH - _mySegementView.frame.size.height)];
        _myScrollView.backgroundColor = [UIColor clearColor];
        _myScrollView.delegate = self;
        _myScrollView.showsVerticalScrollIndicator = NO;
        _myScrollView.showsHorizontalScrollIndicator = NO;
        _myScrollView.bounces = NO;
        _myScrollView.scrollsToTop = NO;
        _myScrollView.pagingEnabled = YES;

    }
    return _myScrollView;
}

//滚动结束,更新按钮下方线条
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if (scrollView==_myScrollView)
    {
        int p=_myScrollView.contentOffset.x / SCROLLVIEW_WIDTH;
        [_mySegementView setPageIndex:p + 1];
    }
}

@end

MySegementView.h

#import <UIKit/UIKit.h>

typedef void (^btnClickedBlock)(int index);

@interface MySegementView : UIView<UIScrollViewDelegate>
{
    int nPageIndex;
    int titleCount;
    UIButton *currentBtn;
    NSMutableArray *btnArray;
}

- (void)setPageIndex:(int)nIndex;

- (instancetype) initWithFrame:(CGRect)frame titleArray : (NSArray *)titleArray block : (btnClickedBlock) clickedBlock;

@property (nonatomic, copy) btnClickedBlock block;

@property (strong, nonatomic) UIScrollView *segementScrollView;

@property (strong, nonatomic) UIView *selectedLine;

@end

MySegementView.m

#import "MySegementView.h"
#define SEGEMENT_BTN_WIDTH 48

@implementation MySegementView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
- (instancetype) initWithFrame:(CGRect)frame titleArray : (NSArray *)titleArray block : (btnClickedBlock) clickedBlock
{
    self = [super initWithFrame:frame];
    [self addSubview:self.segementScrollView];
    if (self) {
        [self setBackgroundColor:[UIColor colorWithRed:0x2d/255.0 green:0x2a/255.0 blue:0x2b/255.0 alpha:1]];
        self.block = clickedBlock;
        nPageIndex = 1;
        titleCount = titleArray.count;
        btnArray = [NSMutableArray array];
        for (int i = 0; i < titleCount; i++) {
            UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(i * SEGEMENT_BTN_WIDTH, 0, SEGEMENT_BTN_WIDTH, 42)];
            [btn setTitle:titleArray[i] forState:UIControlStateNormal];
            btn.titleLabel.font = [UIFont fontWithName:@"Arial" size:14];
            [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
            btn.tag = i + 1;
            [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
            [self.segementScrollView addSubview:btn];
            [btnArray addObject:btn];
        }
        self.selectedLine.frame = CGRectMake(0, 42, SEGEMENT_BTN_WIDTH, 2);
        [self.segementScrollView addSubview: self.selectedLine];
        self.segementScrollView.contentSize = CGSizeMake(titleCount * SEGEMENT_BTN_WIDTH, 0);
    }
    return self;
}

//懒加载
- (UIScrollView *)segementScrollView
{
    if (_segementScrollView == nil) {
        CGRect rect = self.frame;
        _segementScrollView = [[UIScrollView alloc] initWithFrame:rect];
        _segementScrollView.showsHorizontalScrollIndicator = NO;
        _segementScrollView.showsVerticalScrollIndicator = NO;
        _segementScrollView.bounces = NO;
        _segementScrollView.pagingEnabled = NO;
        _segementScrollView.delegate = self;
        _segementScrollView.scrollsToTop = NO;
    }
    return _segementScrollView;
}

//懒加载
- (UIView *)selectedLine
{
    if (_selectedLine == nil) {
        _selectedLine = [[UIView alloc] init];
        _selectedLine.backgroundColor = [UIColor redColor];
    }
    return _selectedLine;
}

//设置当前页面,并更新顶部标签页
- (void)setPageIndex:(int)nIndex
{
    if (nIndex != nPageIndex) {
        nPageIndex = nIndex;
        [self refreshSegement];
    }
}

- (void)refreshSegement
{
    //找到当前选中页面对应的顶部按钮
    for (UIButton *btn in btnArray) {
        if (btn.tag == nPageIndex) {
            currentBtn = btn;
        }
    }

    //如果选中页面对应按钮超出可视范围,顶部滚动视图滚动
    int x = currentBtn.frame.origin.x;
     if (currentBtn.frame.origin.x + SEGEMENT_BTN_WIDTH > self.frame.size.width + self.segementScrollView.contentOffset.x) {
     [self.segementScrollView setContentOffset:CGPointMake(self.segementScrollView.contentOffset.x + SEGEMENT_BTN_WIDTH, 0) animated:YES];
     }
     else if (currentBtn.frame.origin.x < self.segementScrollView.contentOffset.x)
     {
     [self.segementScrollView setContentOffset:CGPointMake(currentBtn.frame.origin.x, 0) animated:YES];
     }

    //下方选中标记线条滚动效果
    [UIView animateWithDuration:0.2 animations:^{
    _selectedLine.frame = CGRectMake(currentBtn.frame.origin.x, self.frame.size.height - 2, SEGEMENT_BTN_WIDTH, 2);
    }completion:^(BOOL finished) {

    }];
}

- (void)btnClick:(UIButton*)btn
{
    currentBtn = btn;
    if (nPageIndex != btn.tag) {
        nPageIndex = btn.tag;
        [self refreshSegement];
        self.block(nPageIndex);
    }
}
@end

使用方法:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSMutableArray *array=[NSMutableArray array];//显示的标签页
    for (int i = 0; i < 12; i++) {
            MyViewController1 *viewController1 = [[MyViewController1 alloc] initWithIndex:i + 1];//initWithIndex : 自定义的构造方法,用于显示页面编号
            [array addObject:viewController1];//滚动视图列表
    }
    myScrollView = [[MyScrollView alloc] initWithFrame:self.view.frame titleArray:@[@"第1页",@"第2页",@"第3页",@"第4页",@"第5页",@"第6页",@"第7页",@"第8页",@"第9页",@"第10页",@"第11页",@"第12页"] viewArray:array];

    [self.view addSubview:myScrollView];
    // Do any additional setup after loading the view, typically from a nib.
}

源码下载链接:http://download.csdn.net/detail/lzm2625347497/9562677

时间: 2024-10-14 20:09:01

IOS UIScrollView + UIButton 实现页面和顶部标签页水平滚动效果的相关文章

HTML标签marquee实现滚动效果

HTML标签marquee实现滚动效果 转载自:http://www.cnblogs.com/zzuIvy/p/marqueeTest_1.html 页面的自动滚动效果,可由javascript来实现,但是今天无意中发现了一个html标签 - <marquee></marquee>可以实现多种滚动效果,无需js控制. 使用marquee标记不仅可以移动文字,也可以移动图片,表格等. 语法:<marquee>...</marquee>: 说明:在标记之间添加要

ActionBar+Fragment实现顶部标签页

用ActionBar的TABS模式,和Fragment实现程序顶部的标签页切换. 一. MainActivity public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 取得ActionB

web前端中实现多标签页切换的效果

在这里,实现多标签页效果的方法有两个,一个是基于DOM的,另一个是基于jquery的,此次我写的是一个对于一个电话套餐的不同,显示不同的标签页 方法一: 首先,我们要把页面的大体框架和样式写出来,html和css代码如下: <ul id="tab">    <li id="tab1" onclick="show(1)">10元套餐</li>    <li id="tab2" oncli

JS魔法堂:通过marquee标签实现信息滚动效果

一.前言   有限的空间展现无限的内容,这是滚动最常用到的地方.根据信息滚动效果我们可以有很多的实现方式,但HTML自带的 marquee标签 是其中一个较简单的实现方式.下面记录一下,供日后查阅. 二. marquee标签 的基础知识 示例: <marquee behavior="scroll" direction="left" loop="-1" scrollAmount="12" scrollDelay="

jquery-ui-bootstrap动态添加和删除标签页封装【效果更炫】

1.效果图 2.导入js和css <link rel="stylesheet" href="css/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="font/Font-Awesome/css/font-awesome.css"> <link rel="styl

java简单博客系统(二)导航标签页点击后页面内容改变及背景色改变

一.同一个Servlet处理多个请求,显示不同的页面内容 导航标签页 bootStrap模板: <ul class="nav nav-tabs"> <li role="presentation" class="active"><a href="#">Home</a></li> <li role="presentation"><a

JS 监听浏览器标签页显示隐藏

JS 监听浏览器标签页显示隐藏 API document.hidden 判断页面是否隐藏的布尔值.页面隐藏包括 页面在后台标签页中 或者 浏览器最小化 document.visibilityState (只读属性), 返回document的可见性,4个值: hidden:文档处于背景标签页或者窗口处于最小化状态,或者操作系统正处于 '锁屏状态' visible:此页面在前景标签页中,并且窗口没有最小化 prerender:页面在屏幕外执行预渲染处理 document.hidden 的值为 tru

20141112 WinForm子窗口标签页

(一)标签页 先看看效果: 代码: 1 public partial class 标签页 : Form 2 { 3 string s = ""; 4 public 标签页() 5 { 6 InitializeComponent(); 7 } 8 /// <summary> 9 /// 判断选项卡中是否有本选项卡 10 /// </summary> 11 /// <param name="s">选项卡名</param>

iOS开发笔记13:顶部标签式导航栏及下拉分类菜单

当内容及分类较多时,往往采用顶部标签式导航栏,例如网易新闻客户端的顶部分类导航,最近刚好有这样的应用场景,参考网络上一些demo,实现了这种导航效果,记录一些要点. 效果图(由于视频转GIF掉帧,滑动和下拉动画显得比较生硬,刚发现quickTime可以直接录制手机视频,推荐一下,很方便) 1.顶部标签式导航栏 (1)实现思路 其实就是在上下两个UIScrollView上做文章,实现联动选择切换的效果. ①顶部标签导航栏topCategoryListScrollView加载显示分类数据,下方con