PageTitleView:

#import <UIKit/UIKit.h>

@class GFBPageTitleView;
@protocol GFBPageTitleViewDelegate <NSObject> - (void)pageTitleView:(GFBPageTitleView *)pageTitleView selectedIndex:(int)index; @end @interface GFBPageTitleView : UIView - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArray;
@property (nonatomic,weak)id<GFBPageTitleViewDelegate> delegate; - (void)setTitleWithProgress:(CGFloat)progress soureceIndex:(int)sourceIndex targetIndex:(int)targetIndex; @end
//
// GFBPageTitleView.m
// elmsc
//
// Created by MAC on 2016/11/26.
// Copyright © 2016年 GFB Network Technology Co.,Ltd. All rights reserved.
// #import "GFBPageTitleView.h" // 线条的高度
#define kScrollLineH 2.0 @interface GFBPageTitleView () @property (nonatomic, strong) NSArray *titlesArray;
@property (nonatomic, strong) NSMutableArray *titlesLabelArray; @property (nonatomic, strong) UIScrollView *contentScrollView;
@property (nonatomic, strong) UIView *scrollLineView;
@property (nonatomic, assign) NSInteger currentIndex; @end @implementation GFBPageTitleView #pragma mark--懒加载
- (UIScrollView *)contentScrollView
{
if (! _contentScrollView) {
_contentScrollView = [[UIScrollView alloc]init];
_contentScrollView.showsHorizontalScrollIndicator = NO;
_contentScrollView.scrollsToTop = NO;
_contentScrollView.bounces = NO;
}
return _contentScrollView;
} - (UIView *)scrollLineView
{
if (! _scrollLineView) {
_scrollLineView = [[UIView alloc]init];
_scrollLineView.backgroundColor = [UIColor orangeColor];
}
return _scrollLineView;
} - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titlesArray
{
self = [super initWithFrame:frame];
if (self) { self.titlesArray = titlesArray;
[self setUpUI];
return self;
}
return nil;
} #pragma mark--Private Methods 自定义方法
- (void) setUpUI
{
self.titlesLabelArray = [NSMutableArray array];
// 添加滚动视图
[self addSubview:self.contentScrollView];
self.contentScrollView.frame = self.bounds; // 添加title对应的Label
[self setUpTitleLabels]; // 设置底线和滚动的滑块
[self setupBottomLineAndScrollLine]; } - (void) setUpTitleLabels
{
// 0.确定label的一些frame的值
CGFloat labelW = self.frame.size.width / (CGFloat)(self.titlesArray.count);
CGFloat labelH = self.frame.size.height - kScrollLineH;
CGFloat labelY = ; [self.titlesArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { UILabel *label = [[UILabel alloc]init];
label.text = obj;
label.tag = idx;
label.font = [UIFont systemFontOfSize:];
label.textColor = [UIColor lightGrayColor];
label.textAlignment = NSTextAlignmentCenter; CGFloat labelX = labelW * (CGFloat)(idx);
label.frame = CGRectMake(labelX, labelY, labelW, labelH);
[self.contentScrollView addSubview:label];
[self.titlesLabelArray addObject:label]; // 添加到数组中 // 添加手势点击
label.userInteractionEnabled = YES; // 允许交互
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(titleLabelClick:)];
[label addGestureRecognizer:tap]; }]; } - (void) setupBottomLineAndScrollLine
{ // 1.添加底线(底部的线暂时不需要)
UIView *bottomLine = [UIView new];
bottomLine.backgroundColor = [UIColor lightGrayColor];
CGFloat lineH = 0.5;
bottomLine.frame = CGRectMake(, self.frame.size.height - lineH, self.frame.size.width, lineH);
//[self addSubview:bottomLine]; // 2.添加scrollLine
// 2.1.获取第一个Label
UILabel *firstLabel = self.titlesLabelArray.firstObject;
firstLabel.textColor = [UIColor lightGrayColor]; // 2.2.设置scrollLine的属性
[self.contentScrollView addSubview:self.scrollLineView];
self.scrollLineView.frame = CGRectMake(firstLabel.frame.origin.x, self.frame.size.height - kScrollLineH, firstLabel.frame.size.width, kScrollLineH);
} #pragma mark--Action 点击方法
- (void) titleLabelClick:(UITapGestureRecognizer *)tapGes
{
// 0.获取当前Label
UILabel *currentLabel = (UILabel *)tapGes.view;
// 1.如果是重复点击同一个Title,那么直接返回
if (currentLabel.tag == self.currentIndex) { return; } // 2.获取之前的Label
UILabel *oldLabel = self.titlesLabelArray[_currentIndex]; // 3.切换文字的颜色
currentLabel.textColor = [UIColor lightGrayColor];
//UIColor(r: kSelectColor.0, g: kSelectColor.1, b: kSelectColor.2)
oldLabel.textColor = [UIColor lightGrayColor];
//UIColor(r: kNormalColor.0, g: kNormalColor.1, b: kNormalColor.2) // 4.保存最新Label的下标值
self.currentIndex = currentLabel.tag; // 5.滚动条位置发生改变
CGFloat scrollLineX = (CGFloat)(_currentIndex) * self.scrollLineView.frame.size.width;
[UIView animateWithDuration:0.15 animations:^{
CGRect rect = self.scrollLineView.frame;
rect.origin.x = scrollLineX;
self.scrollLineView.frame = rect; }]; // 通知代理
[self.delegate pageTitleView:self selectedIndex:(int)self.currentIndex]; } #pragma mark--对外的方法
- (void)setTitleWithProgress:(CGFloat)progress soureceIndex:(int)sourceIndex targetIndex:(int)targetIndex
{
// 1.取出sourceLabel/targetLabel
UILabel *sourceLabel = self.titlesLabelArray[sourceIndex];
UILabel *targetLabel = self.titlesLabelArray[targetIndex]; // 2.处理滑块的逻辑
CGFloat moveTotalX = targetLabel.frame.origin.x - sourceLabel.frame.origin.x;
CGFloat moveX = moveTotalX * progress;
CGRect rect = self.scrollLineView.frame;
rect.origin.x = sourceLabel.frame.origin.x + moveX;
self.scrollLineView.frame = rect; // 3.颜色的渐变(复杂)
// 3.1.取出变化的范围
// let colorDelta = (kSelectColor.0 - kNormalColor.0, kSelectColor.1 - kNormalColor.1, kSelectColor.2 - kNormalColor.2) // 3.2.变化sourceLabel
sourceLabel.textColor = [UIColor lightGrayColor];
//UIColor(r: kSelectColor.0 - colorDelta.0 * progress, g: kSelectColor.1 - colorDelta.1 * progress, b: kSelectColor.2 - colorDelta.2 * progress) // 3.2.变化targetLabel
targetLabel.textColor = [UIColor lightGrayColor];
//UIColor(r: kNormalColor.0 + colorDelta.0 * progress, g: kNormalColor.1 + colorDelta.1 * progress, b: kNormalColor.2 + colorDelta.2 * progress) // 4.记录最新的index
self.currentIndex = targetIndex;
} @end

PageContentView:

//
// GFBPageContentView.h
// elmsc
//
// Created by MAC on 2016/11/26.
// Copyright © 2016年 GFB Network Technology Co.,Ltd. All rights reserved.
// #import <UIKit/UIKit.h> @class GFBPageContentView;
@protocol GFBPageContentViewDelegate <NSObject> - (void)pageContentView:(GFBPageContentView *)view
progress:(CGFloat)progress
sourceIndex:(int)sourceIndex
targetIndex:(int)targetIndex; @end @interface GFBPageContentView : UIView
// 重写方法
- (instancetype)initWithFrame:(CGRect)frame childVcs:(NSMutableArray *) vcArray parentViewController:(UIViewController *) controller; // 对外的暴露方法
-(void)setCurrentIndex:(int)currentIndex; @property (nonatomic, weak)id<GFBPageContentViewDelegate> delegate;
@end
//
// GFBPageContentView.m
// elmsc
//
// Created by MAC on 2016/11/26.
// Copyright © 2016年 GFB Network Technology Co.,Ltd. All rights reserved.
// #import "GFBPageContentView.h" static NSString *ContentCellID = @"ContentCellID";
@interface GFBPageContentView ()<UICollectionViewDataSource,UICollectionViewDelegate,UIScrollViewDelegate> @property (nonatomic, strong) UICollectionView *contentCollectView;
@property (nonatomic, strong) NSMutableArray *childVcArray;
@property (nonatomic, weak) UIViewController *parentViewController; @property (nonatomic, assign) CGFloat startOffsetX;
@property (nonatomic, assign) BOOL isForbidScrollDelegate; @end
@implementation GFBPageContentView #pragma mark--懒加载
- (UICollectionView *) contentCollectView
{
if (! _contentCollectView) {
// 创建布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
layout.itemSize = self.bounds.size;
layout.minimumInteritemSpacing = ;
layout.minimumLineSpacing = ;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; // 2.创建UICollectionView
_contentCollectView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
_contentCollectView.showsHorizontalScrollIndicator = NO;
_contentCollectView.pagingEnabled = YES;
_contentCollectView.bounces = NO;
_contentCollectView.dataSource = self;
_contentCollectView.delegate = self;
_contentCollectView.scrollsToTop = NO;
_contentCollectView.backgroundColor = [UIColor whiteColor]; [_contentCollectView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:ContentCellID]; }
return _contentCollectView;
} #pragma mark--Systems Methods 系统方法
- (instancetype)initWithFrame:(CGRect)frame childVcs:(NSMutableArray *) vcArray parentViewController:(UIViewController *) controller
{
self = [super initWithFrame:frame];
if (self) { self.childVcArray = vcArray;
self.parentViewController = controller;
[self setUpUI];
return self;
}
return nil;
} #pragma mark--Private Methods 自定义方法 私有
- (void) setUpUI{ self.startOffsetX = ;
self.isForbidScrollDelegate = NO; for (UIViewController *vc in self.childVcArray) {
[self.parentViewController addChildViewController:vc];
}
[self addSubview:self.contentCollectView];
self.contentCollectView.frame = self.bounds;
} #pragma mark--对外的暴露方法
// 对外的暴露方法
-(void)setCurrentIndex:(int)currentIndex
{
// 1.记录需要进制执行代理方法
self.isForbidScrollDelegate = YES; // 2.滚动正确的位置
CGFloat offsetX = (CGFloat)(currentIndex) * self.contentCollectView.frame.size.width;
[self.contentCollectView setContentOffset:CGPointMake(offsetX, ) animated:NO];
} #pragma mark-UICollectionView Methods 数据源方法
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.childVcArray.count;
} - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ContentCellID forIndexPath:indexPath];
// 给cell设置内容
for (id view in cell.contentView.subviews) {
[view removeFromSuperview];
} UIViewController *vc = self.childVcArray[indexPath.item];
vc.view.frame = cell.contentView.bounds;
[cell.contentView addSubview:vc.view]; return cell;
} #pragma mark - UIScrollerViewDelegate Methods 代理方法
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
self.isForbidScrollDelegate = NO;
self.startOffsetX = scrollView.contentOffset.x;
} - (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// 0.判断是否是点击事件
if (self.isForbidScrollDelegate) {
return;
} // 1.定义需要的数据
CGFloat progress = ;
int sourceIndex = ;
int targetIndex = ; // 2.判断是左滑还是右滑
CGFloat currentOffsetX = scrollView.contentOffset.x;
CGFloat scrollViewW = scrollView.bounds.size.width;
if (currentOffsetX > self.startOffsetX) { // 左滑 // 1.计算progress
progress = currentOffsetX / scrollViewW - floor(currentOffsetX / scrollViewW); // 2.计算sourceIndex
sourceIndex = (int)(currentOffsetX / scrollViewW); // 3.计算targetIndex
targetIndex = sourceIndex + ;
if (targetIndex >= self.childVcArray.count) {
targetIndex = (int)self.childVcArray.count - ;
} // 4.如果完全划过去
if (currentOffsetX - self.startOffsetX == scrollViewW) {
progress = ;
targetIndex = sourceIndex;
}
}else{ // 右滑 // 1.计算progress
progress = - (currentOffsetX / scrollViewW - floor(currentOffsetX / scrollViewW)); // 2.计算targetIndex
targetIndex = (int)(currentOffsetX / scrollViewW); // 3.计算sourceIndex
sourceIndex = targetIndex + ;
if (sourceIndex >= self.childVcArray.count) {
sourceIndex = (int)self.childVcArray.count - ;
}
} [self.delegate pageContentView:self progress:progress sourceIndex:sourceIndex targetIndex:targetIndex]; } @end

使用:

//
// GFBTypeGoodsDetailViewController.m
// elmsc
//
// Created by MAC on 2016/11/26.
// Copyright © 2016年 GFB Network Technology Co.,Ltd. All rights reserved.
// #import "GFBTypeGoodsDetailViewController.h"
#import "GFBPageTitleView.h"
#import "GFBPageContentView.h"
#import "GFBCommentViewController.h"
#import "GFBProductViewController.h"
#import "GFBProuctDetailViewController.h" @interface GFBTypeGoodsDetailViewController ()<GFBPageTitleViewDelegate,GFBPageContentViewDelegate> @property (nonatomic, strong) GFBPageTitleView *pageTitleView;
@property (nonatomic, strong) GFBPageContentView *pageContentView; @end @implementation GFBTypeGoodsDetailViewController #pragma mark--懒加载
- (GFBPageTitleView *)pageTitleView
{
if (! _pageTitleView) {
NSMutableArray *arry = [NSMutableArray arrayWithObjects:@"产品",@"详情",@"评价", nil];
_pageTitleView = [[GFBPageTitleView alloc]initWithFrame:CGRectMake(, , * frameW / 375.0, ) titles:arry];
_pageTitleView.delegate = self;
}
return _pageTitleView;
} - (GFBPageContentView *)pageContentView
{
if (! _pageContentView) {
NSMutableArray *vcArray = [NSMutableArray array];
// 产品
GFBProductViewController *productVc = [GFBProductViewController new];
// 详情
GFBProuctDetailViewController *productDetailVc = [GFBProuctDetailViewController new];
// 评论
GFBCommentViewController *commentVc = [GFBCommentViewController new];
[vcArray addObject:productVc];
[vcArray addObject:productDetailVc];
[vcArray addObject:commentVc]; _pageContentView = [[GFBPageContentView alloc]initWithFrame:CGRectMake(, , frameW, frameH - ) childVcs:vcArray parentViewController:self];
//NSLog(@"当前的高度%f",self.view.bounds.size.height);
_pageContentView.delegate = self; }
return _pageContentView;
} - (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.title = @"商品详情";
} - (void)viewDidLoad {
[super viewDidLoad];
[self setUpUI];
} #pragma mark-Private Methods 自定义方法
- (void) setUpUI
{
[self setUpNavBar];
[self setUpContentView];
} - (void) setUpNavBar
{
self.navigationItem.titleView = self.pageTitleView;
} - (void) setUpContentView
{
[self.view addSubview:self.pageContentView];
} #pragma mark-GFBPageTitleViewDelegate Method
- (void)pageTitleView:(GFBPageTitleView *)pageTitleView selectedIndex:(int)index
{
[self.pageContentView setCurrentIndex:index];
} #pragma mark-GFBPageContentViewDelegate Method
- (void)pageContentView:(GFBPageContentView *)view progress:(CGFloat)progress sourceIndex:(int)sourceIndex targetIndex:(int)targetIndex
{
[self.pageTitleView setTitleWithProgress:progress soureceIndex:sourceIndex targetIndex:targetIndex];
} @end

第十四篇、OC_新闻查看器的更多相关文章

  1. 第十四篇 Integration Services:项目转换

    本篇文章是Integration Services系列的第十四篇,详细内容请参考原文. 简介在前一篇,我们查看了SSIS变量,变量配置和表达式管理动态值.在这一篇,我们使用SQL Server数据商业 ...

  2. 【译】第十四篇 Integration Services:项目转换

    本篇文章是Integration Services系列的第十四篇,详细内容请参考原文. 简介在前一篇,我们查看了SSIS变量,变量配置和表达式管理动态值.在这一篇,我们使用SQL Server数据商业 ...

  3. 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)

    解剖SQLSERVER 第十四篇    Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...

  4. Egret入门学习日记 --- 第十四篇(书中 5.4~5.6节 内容)

    第十四篇(书中 5.4~5.6节 内容) 书中内容: 总结 5.4节 内容重点: 1.如何编写自定义组件? 跟着做: 重点1:如何编写自定义组件? 文中提到了重要的两点. 好,我们来试试看. 第一步, ...

  5. Spring Cloud第十四篇 | Api网关Zuul

    ​ 本文是Spring Cloud专栏的第十四篇文章,了解前十三篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring C ...

  6. Python之路【第十四篇】:AngularJS --暂无内容-待更新

    Python之路[第十四篇]:AngularJS --暂无内容-待更新

  7. 跟我学SpringCloud | 第十四篇:Spring Cloud Gateway高级应用

    SpringCloud系列教程 | 第十四篇:Spring Cloud Gateway高级应用 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 ...

  8. SpringBoot第二十四篇:应用监控之Admin

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11457867.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   前一章(S ...

  9. Hibernate(十四篇)

    (一)Hibernate简介 (二)hibernate配置管理 (三)Hibernate对象-关系映射文件 (四)Hibernate API详解 (五)Hibernate一级缓存 (六)Hiberna ...

随机推荐

  1. Eclipse设置每行代码的长度

    打开 Window -> preferences -> java -> code style -> formatter -> edit -> line wrappi ...

  2. 大数据量高并发访问SQL优化方法

    保证在实现功能的基础上,尽量减少对数据库的访问次数:通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担:能够分开的操作尽量分开处理,提高每次的响应速度:在数据窗口使用SQL时,尽量把 ...

  3. MYSQL性能优化之Mysql数据库监控

    监控对象 数据库可用性监控数据库进程或是端口存在并不意味着数据库就是可用的 也就是说登陆服务器,并且能正确执行mysql命令 数据库性能 QPS和DPS并发线程数量(同时执行sql语句的数量,不是连接 ...

  4. phpcms文件结构

    主要目录部分 /admin 管理后台目录       -- /skin/    后台样式       -- /templates/    后台样式模板 /api api接口 /corpandresiz ...

  5. 为什么有人会觉得IT门槛低,工资高?

    今天在高铁上,翻着逼乎,被一个话题勾住了,"为什么很多人会觉得IT门槛低?" 我一惊,还真是,身边朋友都觉得"IT赚的多","程序员工资高" ...

  6. 《C#高效编程》读书笔记05-为类型提供ToString()方法

    System.Object.ToString()是.NET环境中最常用的方法之一.编写类型时,要提供一个合理的ToString版本,否则使用者就不得不自己构造一套可以阅读的表示. public cla ...

  7. Java 类型转换String,List,Map,Array

    1. JsonString转为Map String jsoNStr = "{\n" + "\t\"TestArray\": [\"1\&qu ...

  8. ORACLE将查询的多条语句拼在一个字段下

    select listagg(字段名,'分隔符') within group (order by 某个字段)

  9. 《Head First 设计模式》之模板方法模式——冲泡咖啡和茶

    模板方法模式(Template) ——在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 好莱坞原则:别调用(打电话给 ...

  10. 《Head First 设计模式》之策略模式——鸭子行为

    策略模式(Strategy Pattern) ——定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. (每个功能的多种实现成为一个算法族,这些算法族被分别封装 ...