iOS 页面滑动与标题切换颜色渐变的联动效果实例
发布时间 - 2026-01-11 00:34:39 点击率:次话不多说,直接上图,要实现类似如下效果。
这个效果非常常见,这里着重讲讲核心代码
封装顶部的PageTitleView
封装构造函数
封装构造函数,让别人在创建对象时,就传入其实需要显示的内容 frame:创建对象时确定了
- frame就可以直接设置子控件的位置和尺寸
- isScrollEnable:是否可以滚动。某些地方该控件是可以滚动的。
- titles:显示的所有标题
// MARK:- 构造函数
init(frame: CGRect, isScrollEnable : Bool, titles : [String]) {
selfisScrollEnable = isScrollEnable
selftitles = titles
superinit(frame: frame)
}
设置UI界面
设置UI界面
- 添加UIScrollView,如果标题过多,则可以滚动
- 初始化所有的Label,用于显示标题。并且给label添加监听手势
- 添加顶部线和滑块的View
实现相对来说比较简单,这里代码从略
封装底部的PageCotentView
封装构造函数
封装构造函数,让别人在创建对象时,就传入其实需要显示的内容
- 所有用于显示在UICollectionView的Cell的所有控制器
- 控制器的父控制器
// MARK:- 构造函数
init(frame: CGRect, childVcs : [UIViewController], parentViewController : UIViewController) {
selfchildVcs = childVcs
selfparentViewController = parentViewController
superinit(frame: frame)
}
设置UI界面内容
设置UI界面
- 将所有的子控制器添加到父控制器中
- 添加UICollectionView,用于展示内容
// MARK:- 懒加载属性
private lazy var collectionView : UICollectionView = {
// 1.创建布局
let layout = UICollectionViewFlowLayout()
layout.itemSize = self.bounds.size
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.scrollDirection = .Horizontal
// 2.创建collectionView
let collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
collectionView.showsHorizontalScrollIndicator = false
collectionView.pagingEnabled = true
collectionView.bounces = false
collectionView.scrollsToTop = false
collectionView.dataSource = self
collectionView.delegate = self
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: kContentCellID)
return collectionView
}()
private func setupUI() {
// 1.添加所有的控制器
for childVc in childVcs {
parentViewController?.addChildViewController(childVc)
}
// 2.添加collectionView
addSubview(collectionView)
}
实现UICollectionView的数据源方法
- 在返回Cell的方法中,先将cell的contentView中的子控件都移除,防止循环引用
- 取出indexPath.item对应的控制器,将控制器的View添加到Cell的contentView中
// MARK:- 遵守UICollectionView的数据源
extension PageContentView : UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return childVcs.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(kContentCellID, forIndexPath: indexPath)
// 移除之前的
for subview in cell.contentView.subviews {
subview.removeFromSuperview()
}
// 取出控制器
let childVc = childVcs[indexPath.item]
childVc.view.frame = cell.contentView.bounds
cell.contentView.addSubview(childVc.view)
return cell
}
}
PageTitleView点击改变PageContentView
通过代理将PageTitleView的事件传递出去
/// 定义协议
protocol PageTitleViewDelegate : class {
func pageTitleView(pageTitleView : PageTitleView, didSelectedIndex index : Int)
}
@objc private func titleLabelClick(tapGes : UITapGestureRecognizer) {
// 1.获取点击的下标志
guard let view = tapGes.view else { return }
let index = view.tag
// 2.滚到正确的位置
scrollToIndex(index)
// 3.通知代理
delegate?.pageTitleView(self, didSelectedIndex: index)
}
内部调整
// 内容滚动
private func scrollToIndex(index : Int) {
// 1.获取最新的label和之前的label
let newLabel = titleLabels[index]
let oldLabel = titleLabels[currentIndex]
// 2.设置label的颜色
newLabel.textColor = kSelectTitleColor
oldLabel.textColor = kNormalTitleColor
// 3.scrollLine滚到正确的位置
let scrollLineEndX = scrollLine.frame.width * CGFloat(index)
UIView.animateWithDuration(0.15) {
self.scrollLine.frame.origin.x = scrollLineEndX
}
// 4.记录index
currentIndex = index
}
在PageContentView中设置当前应该滚动的位置
// MARK:- 对外暴露方法
extension PageContentView {
func scrollToIndex(index : Int) {
let offset = CGPoint(x: CGFloat(index) * collectionViewboundswidth, y: 0)
collectionViewsetContentOffset(offset, animated: false)
}
}
PageContentView滚动调整PageTitleView
通过观察,我们发现:
1> 原来位置的Title颜色会逐渐变暗
2> 目标位置的Title颜色会逐渐变亮
3> 变化程度是和滚动的多少相关
由此得出结论:
我们一共需要获取三个值
1> 起始位置下标值
2> 目标位置下标值
3> 当前滚动的进度
其实前2点可以由第3点计算而来,可以只需要将进度传递出去。
根据进度值处理标题颜色渐变及滑块逻辑
。当前进度值唯一确定了标题的状态,计算出需要发生颜色变化的两相邻标题索引
。注意:下标值需要防止越界问题,临界点的处理
实现代码
extension PageContentView : UICollectionViewDelegate {
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
startOffsetX = scrollView.contentOffset.x
}
func scrollViewDidScroll(scrollView: UIScrollView) {
// 0.判断是否是点击事件
if isForbidScrollDelegate { return }
// 1.定义获取需要的数据
var progress : CGFloat = 0
let currentOffsetX = scrollView.contentOffset.x
let scrollViewW = scrollView.bounds.width
// 1.计算progress
progress = currentOffsetX / scrollViewW
// 3.将progress传递给titleView
delegate?.pageContentView(self, progress: progress)
}
}
根据滚动传入的值,调整PageTitleView
两种颜色必须使用RGB值设置(方便通过RGB实现渐变效果)
private let kNormalRGB : (CGFloat, CGFloat, CGFloat) = (85, 85, 85) private let kSelectRGB : (CGFloat, CGFloat, CGFloat) = (255, 128, 0) private let kDeltaRGB = (kSelectRGB.0 - kNormalRGB.0, kSelectRGB.1 - kNormalRGB.1, kSelectRGB.2 - kNormalRGB.2) private let kNormalTitleColor = UIColor(red: 85/255.0, green: 85/255.0, blue: 85/255.0, alpha: 1.0) private let kSelectTitleColor = UIColor(red: 255.0/255.0, green: 128/255.0, blue: 0/255.0, alpha: 1.0)
调整scrollLine及两个Label颜色渐变
// MARK:- 对外暴露方法
extension PageTitleView
func changeLabel(progress: CGFloat) {
// 开启弹簧效果时的过滤处理
var progress = progress > 0 ? progress : 0
progress = progress <= CGFloat(titleLabels.count - 1) ? progress : CGFloat(titleLabels.count - 1)
var leftLabelIndex = Int(floor(progress))
let ratio = progress - CGFloat(leftLabelIndex)
//获取leftLabel和rightLabel
let leftLabel = titleLabels[leftLabelIndex]
if leftLabelIndex >= 3{
leftLabelIndex = 3
}
print("leftLabelIndex = \(leftLabelIndex)")
var rightIndex = leftLabelIndex + 1
if rightIndex >= 3{
rightIndex = 3
}
print("rightIndex = \(rightIndex)")
let rightLabel = titleLabels[rightIndex]
//滑块的逻辑
let moveTotalX = leftLabel.frame.width
let moveX = moveTotalX * ratio
scrollLine.frame.origin.x = leftLabel.frame.origin.x + moveX
//3.Label颜色的渐变
// 3.1.取出变化的范围
let colorDelta = (kSelectedColor.0 - kNormalColor.0, kSelectedColor.1 - kNormalColor.1, kSelectedColor.2 - kNormalColor.2)
if leftLabelIndex != rightIndex {
// 3.2.变化leftLabel
leftLabel.textColor = UIColor(r: kSelectedColor.0 - colorDelta.0 * ratio, g: kSelectedColor.1 - colorDelta.1 * ratio, b: kSelectedColor.2 - colorDelta.2 * ratio)
// 3.2.变化rightLabel
rightLabel.textColor = UIColor(r: kNormalColor.0 + colorDelta.0 * ratio, g: kNormalColor.1 + colorDelta.1 * ratio, b: kNormalColor.2 + colorDelta.2 * ratio)
}
// 4.记录最新的index
currentIndex = leftLabelIndex
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# ios
# 导航栏滑动渐变
# 标题栏渐变
# iOS Segment带滑动条切换效果
# iOS使用pageViewController实现多视图滑动切换
# 浅析iOS多视图滑动点击切换的集成
# iOS Objective-c实现左右滑动切换页面
# 滑块
# 移除
# 确定了
# 两种
# 而来
# 只需
# 要将
# 则可
# 多说
# 先将
# 大家多多
# 计算出
# 就可以
# 上图
# 判断是否
# 器中
# 加载
# 变暗
# 变亮
# collectionViewLayout
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
详解Android——蓝牙技术 带你实现终端间数据传输
HTML 中动态设置元素 name 属性的正确语法详解
Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层
绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信
Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】
Laravel如何实现全文搜索功能?(Scout和Algolia示例)
手机软键盘弹出时影响布局的解决方法
如何用好域名打造高点击率的自主建站?
EditPlus中的正则表达式 实战(2)
如何批量查询域名的建站时间记录?
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
如何在七牛云存储上搭建网站并设置自定义域名?
如何为不同团队 ID 动态生成多个“认领值班”按钮
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
Python图片处理进阶教程_Pillow滤镜与图像增强
Laravel项目怎么部署到Linux_Laravel Nginx配置详解
jquery插件bootstrapValidator表单验证详解
Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
焦点电影公司作品,电影焦点结局是什么?
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
动图在线制作网站有哪些,滑动动图图集怎么做?
重庆市网站制作公司,重庆招聘网站哪个好?
Laravel如何为API生成Swagger或OpenAPI文档
浅述节点的创建及常见功能的实现
如何自定义建站之星模板颜色并下载新样式?
ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】
如何在香港服务器上快速搭建免备案网站?
网站优化排名时,需要考虑哪些问题呢?
iOS发送验证码倒计时应用
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址
手机网站制作与建设方案,手机网站如何建设?
Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全
如何在建站之星网店版论坛获取技术支持?
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
如何用PHP工具快速搭建高效网站?
Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)
Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
敲碗10年!Mac系列传将迎来「触控与联网」双革新
Python结构化数据采集_字段抽取解析【教程】
如何快速搭建FTP站点实现文件共享?
Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程
Laravel如何生成和使用数据填充?(Seeder和Factory示例)
Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】

