封装了一个iOS联动滚动效果

效果图

请添加图片描述

实现逻辑和原理

就是在 didEndDisplayingCell 方法中通过indexPathsForVisibleItems 接口获取当前可见的cell对应的indexPath, 然后获取到item最小的那一个,即可,同时,还要在 willDisplayCell 方法中直接设置标题的选中属性,否则
由于重用机制,导致选中的展示错乱

代码

//
//  LBLinkedContentView.m
//  LBTwoLinkedScrollingCollectionView
//
//  Created by mac on 2024/6/25.
//#import "LBLinkedContentView.h"
#import "LBLinkedContentViewTittleCell.h"
#import "LBLinkedContentViewContentCell.h"@interface LBLinkedContentView () <UICollectionViewDelegate, UICollectionViewDataSource>@property (nonatomic, strong) UICollectionView *titleView;
@property (nonatomic, strong) UICollectionView *contentView;@property (nonatomic, strong) NSMutableArray *titleArray;
@property (nonatomic, strong) NSMutableArray *contentArray;@property (nonatomic, strong) NSIndexPath *selectedGroupIndex;@end@implementation LBLinkedContentView- (instancetype)initWithFrame:(CGRect)frame
{if (self = [super initWithFrame:frame]) {[self configData];[self setUpUI];}return self;
}- (void)setUpUI
{[self addSubview:self.titleView];[self addSubview:self.contentView];[self.titleView reloadData];[self.contentView reloadData];self.selectedGroupIndex = [NSIndexPath indexPathForRow:0 inSection:0];LBLinkedContentViewTittleCell *titleCell = [self.titleView cellForItemAtIndexPath:self.selectedGroupIndex];titleCell.selected = YES;
}#pragma mark - configData- (void)configData
{for (int i = 0; i < 10; i ++)  {NSString *title = [NSString stringWithFormat:@"%d",i];[self.titleArray addObject:title];NSMutableArray *array = [NSMutableArray array];for (int j = 0; j < 10; j ++) {NSString *content = [NSString stringWithFormat:@"第%d分区第%d条", i,j];[array addObject:content];}[self.contentArray addObject:array];}
}#pragma mark - data Delegate- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{if (collectionView == self.contentView) {LBLinkedContentViewContentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewContentCell class]) forIndexPath:indexPath];NSString *title = self.contentArray[indexPath.section][indexPath.item];[cell updateWithContent:title];return cell;}LBLinkedContentViewTittleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewTittleCell class]) forIndexPath:indexPath];[cell updateWithIndexPath:indexPath];return cell;
}- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{if (collectionView == self.titleView) {return 1;}return self.contentArray.count;
}- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{return 10;
}- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{if (collectionView == self.titleView) {if (self.selectedGroupIndex && [self.selectedGroupIndex compare:indexPath] == NSOrderedSame) {cell.selected = YES;} else {cell.selected = NO;}}
}- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{if (collectionView == self.contentView) {[self handleGroupViewWithIndex:nil];}
}#pragma mark - private- (void)handleGroupViewWithIndex:(NSIndexPath *)indexPathCell
{NSArray <NSIndexPath *> *visibleIndexPaths = [self.contentView indexPathsForVisibleItems];if (!visibleIndexPaths.count) {return;}NSInteger section = indexPathCell ? indexPathCell.section : [self.contentView numberOfSections] - 1;for (NSIndexPath *indexPath in visibleIndexPaths) {if (indexPath.section < section) {section = indexPath.section;}}NSIndexPath *groupIndexPath = [NSIndexPath indexPathForItem:section inSection:0];if(self.selectedGroupIndex && [self.selectedGroupIndex compare:groupIndexPath] != NSOrderedSame) {LBLinkedContentViewTittleCell *cell = [self.titleView cellForItemAtIndexPath:self.selectedGroupIndex];cell.selected = NO;self.selectedGroupIndex = groupIndexPath;LBLinkedContentViewTittleCell *titleCell = [self.titleView cellForItemAtIndexPath:groupIndexPath];titleCell.selected = YES;[self.titleView scrollToItemAtIndexPath:groupIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];}
}#pragma mark - lazy load- (UICollectionView *)titleView
{if (!_titleView) {UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];layout.minimumLineSpacing = 29;layout.minimumInteritemSpacing = 29;layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;layout.itemSize = CGSizeMake(40, 50);_titleView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 60) collectionViewLayout:layout];[_titleView registerClass:[LBLinkedContentViewTittleCell class] forCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewTittleCell class])];_titleView.delegate = self;_titleView.dataSource = self;}return _titleView;
}- (UICollectionView *)contentView
{if (!_contentView) {UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];layout.minimumLineSpacing = 10;layout.minimumInteritemSpacing = 10;layout.itemSize = CGSizeMake(100, 80);layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;layout.sectionInset = UIEdgeInsetsMake(0, 40, 0, 40);_contentView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 80, CGRectGetWidth(self.bounds), 80) collectionViewLayout:layout];[_contentView registerClass:[LBLinkedContentViewContentCell class] forCellWithReuseIdentifier:NSStringFromClass([LBLinkedContentViewContentCell class])];_contentView.delegate = self;_contentView.dataSource = self;_contentView.backgroundColor = [UIColor yellowColor];}return _contentView;
}- (NSMutableArray *)titleArray
{if (!_titleArray) {_titleArray = [NSMutableArray array];}return _titleArray;
}- (NSMutableArray *)contentArray
{if (!_contentArray) {_contentArray = [NSMutableArray array];}return _contentArray;
}@end

link

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/860531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【杂记-OSI参考模型之传输层】

OSI参考模型之传输层 一、传输层概述二、传输层工作原理1、分段与重组2、端口号的使用3、连接控制4、流量控制与拥塞控制5、差错检测 一、传输层概述 传输层作为网络通信模型中的关键层次&#xff0c;主要负责提供端到端的通信服务&#xff0c;是网络通信的核心环节。它不仅确…

cropperjs 裁剪/框选图片

1.效果 2.使用组件 <!-- 父级 --><Cropper ref"cropperRef" :imgUrl"url" searchImg"searchImg"></Cropper>3.封装组件 <template><el-dialog :title"title" :visible.sync"dialogVisible" wi…

新人学习笔记之(标识符和键盘录入)

一、标识符 1.标识符是&#xff1a;代码中所有我们自己起的名字&#xff0c;比如变量名、函数名等。 2.命名规则---硬性要求 由数字、字母、下划线(_)组成 不能以数字开头 不能是关键字 区分大小写 3.命名规则---软性要求 用英文单词&#xff0c;见名知意 变量名&#xff1a;全…

Steam怎么卸载DLC Steam怎么只卸载DLC不卸载游戏教程

我们玩家在steam中玩游戏&#xff0c;有一个功能特别重要&#xff0c;那就是DLC&#xff0c;其实也就是一款游戏的扩展&#xff0c;很多游戏都有DLC&#xff0c;让游戏玩法特别丰富&#xff0c;比如都市天际线的DLC&#xff0c;给城市中就增加了很多建筑&#xff0c;或者更便捷…

web前端——CSS

目录 一、css概述 二、基本语法 1.行内样式表 2.内嵌样式表 3.外部样式表 4.三者对比 三、选择器 1.常用的选择器 2. 选择器优先级 3.由高到低优先级排序 四、文本,背景,列表,伪类,透明 1.文本 2.背景 3.列表 4.伪类 5.透明 五、块级,行级,行级块标签, dis…

TikTok达人背后的品牌影响力与用户增长

TikTok独特的算法和广泛的用户基础&#xff0c;使得品牌在TikTok上的推广活动变得尤为重要。在这种背景下&#xff0c;TikTok达人合作成为品牌推广、用户增长和社交影响力的重要工具。本文Nox聚星将和大家探讨TikTok达人合作在这些方面的作用。 一、对品牌推广的作用 1. 增加…

前端科举八股文-性能优化篇

前端科举八股文-性能优化篇 常见的前端性能优化方案&#xff1f;css精灵图的原理&#xff1f;说说懒加载的原理什么是防抖节流&#xff1f;什么是重绘和重排&#xff0c;如何减少重绘和重排如何减少重排&#xff1f;webpack是干什么的&#xff1f;简历上写到你使用了vite&#…

Redis集群-计算key的插槽值等命令

文章目录 1、集群方式登录主机63792、计算key应该保存在那个插槽3、计算某个插槽中保存的key的数量4、返回指定槽中的键5、查看redis的版本5.1、Redis集群的自动故障转移5.2、主节点下线&#xff0c;从节点自动升为主节点5.2.1、杀死主节点63795.2.2、登录从机6383&#xff0c;…

AI大模型企业应用实战-Prompt让LLM理解知识

1 Prompt Prompt 可理解为指导AI模型生成特定类型、主题或格式内容的文本。 NLP中&#xff0c;Prompt 通常由一个问题或任务描述组成&#xff0c;如“给我写一篇有关RAG的文章”&#xff0c;这句话就是Prompt。 Prompt赋予LLM小样本甚至零样本学习的能力&#xff1a; LLM能力…

【网络安全学习】漏洞扫描:-03- Nikito与Wapiti漏洞扫描的使用

1️⃣ Nikto漏洞扫描 Nikto是一个开源的Web扫描评估程序&#xff0c;它可以对目标Web服务器进行快速而全面的检查&#xff0c;以发现各种潜在的安全问题和漏洞。 &#x1f170;️ 如何使用 ❓ nikto -Display 1234ep -h [域名或IP地址] -o nikto.html # -h参数&#xff1a;指…

GitHub每日最火火火项目(6.25)

modelscope / DiffSynth-Studio&#xff1a; 项目介绍&#xff1a;DiffSynth-Studio 是一个基于 Diffusion 模型的创意工具&#xff0c;让用户能够享受扩散模型的神奇魔力。它可能提供了一系列功能和接口&#xff0c;使用户能够探索和生成各种创意内容&#xff0c;如音乐、图像…

栈与队列 Leetcode 347 前k个高频元素

栈与队列 Leetcode 347 前k个高频元素 Leetcode 347 灵活运用C库函数&#xff0c;使用匿名函数排序&#xff0c;sort可以替换为快排实现&#xff08;面试感觉可能会手撕&#xff0c;机考直接使用sort&#xff09; class Solution { public:vector<int> topKFrequent(v…

南昌服务器托管让数据存储更安全

南昌&#xff0c;作为长江中游地区的重要中心城市&#xff0c;近年来经济发展迅速&#xff0c;产业结构不断优化。随着大数据、云计算、人工智能等新一代信息技术的快速发展&#xff0c;南昌的信息化建设步伐不断加快&#xff0c;为企业提供了良好的发展环境。在这样的背景下&a…

xml----命名空间详解

一、XML 命名空间&#xff08;namespace&#xff09;------ xmlns 属性 我们使用xmlns 属性来指定元素的命名空间&#xff0c;格式如下&#xff1a; xmlns:namespace-prefix“namespaceURI” 即 xmlns:前缀“命名空间” xmlns 是 xml namespace的意思&#xff0c;是xml文件规范…

通过迭代器删除容器中的元素

通过之前的介绍我们知道通过迭代器来遍历单例集合的操作仍然需要借助于循环结构。而且我们知道在单例集合中调用iterator方法返回的Iterator对象中还有一个remove方法我们没有介绍&#xff0c;它的作用是删除容器中的元素。说道这里应该有人会发现一个很明显的问题&#xff0c;…

RockChip Android12 Launcher3启动与布局分析

目录 一:概述 二:编译 三:启动 1、AndroidManifest.xml 2、Launcher 四:布局 1、LauncherAppState 2、InvariantDeviceProfile 3、initGrid 4、getPredefinedDeviceProfiles 5、invDistWeightedInterpolate 6、initGrid 7、initDeviceProfile 8、DeviceProfil…

[MySql]两阶段提交

文章目录 什么是binlog使用binlog进行恢复的流程 什么是redolog缓冲池redologredolog结构 两阶段提交 什么是binlog binlog是二进制格式的文件&#xff0c;用于记录用户对数据库的修改&#xff0c;可以作用于主从复制过程中数据同步以及基于时间点的恢复&#xff08;PITR&…

Webpack: 借助 Babel+TS+ESLint 构建现代 JS 工程环境

概述 Webpack 场景下处理 JavaScript 的三种常用工具&#xff1a;Babel、TypeScript、ESLint 的历史背景、功能以及接入 Webpack 的步骤借助这些工具&#xff0c;我们能构建出更健壮、优雅的 JavaScript 应用 使用 Babel ECMAScript 6.0(简称 ES6) 版本补充了大量提升 JavaSc…

互联网应用主流框架整合之Spring Boot运维体系

先准备个简单的系统&#xff0c;配置和代码如下 # 服务器配置 server:# 服务器端口port: 8001# Spring Boot 配置 spring:# MVC 配置mvc:# Servlet 配置servlet:# Servlet 的访问路径path: /sbd# 应用程序配置application:# 应用程序名称name: SpringBootDeployment# 配置数据…

第 133 场 LeetCode 双周赛题解

A 使所有元素都可以被 3 整除的最少操作数 遍历 n u m s nums nums &#xff0c;每有一个不被 3 3 3 整除的数&#xff0c;则操作数加 1 1 1 class Solution {public:int minimumOperations(vector<int>& nums) {int res 0;for (auto x : nums)if (x % 3 ! 0)res…