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. 7、python数据类型之集合set

    数据类型之集合setset 不允许重复的无序集合,不能通过下标取值,因为无序1.创建   创建空集合   s ={} 默认类型为字典,所以不是空集合,空集合如下   s = set()   s = { ...

  2. C# JObject将json字符串转为json对象

    static void Main(string[] args) { string json = "{\"name\": \"测试\",\"m ...

  3. Mysql遍历大表(Mysql大量数据读取内存溢出的解决方法)

    mysql jdbc默认把select的所有结果全部取回,放到内存中,如果是要遍历很大的表,则可能把内存撑爆. 一种办法是:用limit,offset,但这样你会发现取数据的越来越慢,原因是设置了of ...

  4. Docker从入门到实战(二)

    Docker从入门到实战(二) 一:什么是docker Docker是一个开源的应用容器引擎,开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到主流的Linux.MacOS.Windo ...

  5. python模块之datetime方法详细介绍

    datetime Python提供了许多内置模块用于操作时间日期,如calendar,time,datetime,这篇文章主要是对datetime进行汇总,datetime模块的借口实现原则更加直观, ...

  6. 存储过程 jdbc

    package com.itheima.procedure; import java.sql.CallableStatement; import java.sql.Connection; import ...

  7. 牛客网Java刷题知识点之匿名对象

    不多说,直接上干货! 匿名对象的两种用途: 1.当对象对方法仅进行一次调用的时候,就可以简化成匿名对象. 2.匿名对象可以作为实际参数进行传递. 匿名对象顾名思义就是没有名字的对象. new Car( ...

  8. js中的onclick事件传参需要注意的问题

    如果参数是数值类型可以直接传,如果是字符串类型需要在字符串前后加上双引号,双引号需要转义 如 onclick="test(0)";  直接传值 参数为数值 onclick=&quo ...

  9. Entity Framework小知识

    记录在使用EF中使用的技巧,以备查阅. 1.当需要查询一个列总和的时候,如果列是允许NULL或者未查到信息的时候,想要返回的是0 而非NULL时 db.表名.Sum(p=> (decimal?) ...

  10. <linux下extmail服务的搭建>

    下载2个软件包: extmail-1.1.0.tar.gz     extman-1.1.tar.gz 下载地址:http://www.cpan.org/ 创建extsuite目录 mkdir /va ...