当前位置: 首页 > article >正文

iOS实现在collectionView顶部插入数据效果

有时候,我们会遇到这种需求,就是下拉刷新的时候,在
collectionView顶部插入数据,这个时候,需要我们注意
主要有两点
1 关闭隐式动画
由于我们使用insert在collectionView顶部插入数据是有从头部插入的隐式动画的,这个不符合我们的需要,所以要关闭隐式动画 [CATransaction setDisableActions:YES];

2 我们执行过插入数据操作之后,还要将偏移量滚动到之前展示的位置达到在页面顶部插入数据的效果,所以我们要精确的捕获到插入结束的时机,就需要用到performBatchUpdates 方法,在结束的回调中设置偏移量

3 因为涉及到如果没有上一页了,要修改列表的头部,
因为刷新视图就是在头部中,这个时候(头部在顶部,未展示出来),我们需要使用performBatchUpdates 刷新列表,而不能使用reloadData,因为reloadData 刷新头部的时候,会造成列表的cell偏移, 而performBatchUpdates 则不会

代码

//
//  LBUpdateBatchViewController.m
//  TEXT
//
//  Created by mac on 2025/1/4.
//  Copyright © 2025 刘博. All rights reserved.
//

#import "LBUpdateBatchViewController.h"
#import "PerformBatchCell.h"

@interface LBUpdateBatchViewController () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

@property (nonatomic, strong) UICollectionView *collectionView;

@property (nonatomic, strong) UIButton *firstButton;
@property (nonatomic, strong) UIButton *secondButton;

@property (nonatomic, strong) UIButton *thirdButton;

@property (nonatomic, assign) NSInteger flag;

@property (nonatomic, assign) NSInteger itemCount;

@end

@implementation LBUpdateBatchViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.flag = 1;
    self.itemCount = 20;
    [self.view addSubview:self.collectionView];
    [self.view addSubview:self.firstButton];
    [self.view addSubview:self.secondButton];
    [self.view addSubview:self.thirdButton];
    
    // Do any additional setup after loading the view.
}

- (void)firstClick
{
    self.flag = 0;
    [self.collectionView reloadData];
}

- (void)secondClick
{
    self.flag = 2;
    [self.collectionView performBatchUpdates:nil completion:nil];
}

- (void)loadPreviousPage
{
    self.itemCount += 6;
    NSMutableArray *array = [NSMutableArray array];
    for (int i = 0; i < 6; i ++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        [array addObject:indexPath];
    }
    [CATransaction setDisableActions:YES];
    [self.collectionView performBatchUpdates:^{
        [self.collectionView insertItemsAtIndexPaths:array];
        } completion:^(BOOL finished) {
            [CATransaction setDisableActions:NO];
            if (finished) {
                CGRect frame = [self.collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:6 inSection:0]].frame;
                [self.collectionView setContentOffset:CGPointMake(0, frame.origin.y - 100)];
                self.flag --;
                if (self.flag <= 0) {
                    ///注意,这里一定要用 performBatchUpdates 不能用reloadData
                    [self.collectionView performBatchUpdates:nil completion:nil];
                }
            }
        }];

}

#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.itemCount;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        UICollectionReusableView *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];
        header.backgroundColor = [UIColor cyanColor];
        return header;
    }
    return nil;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    CGFloat height = 0;
    if (self.flag >  0) {
        height = 100;
    }
    return CGSizeMake(300, height);
}


- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    PerformBatchCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
    NSString *title = [NSString stringWithFormat:@"%ld", indexPath.item];
    [cell updateWithText:title];
    return cell;
}

- (UICollectionView *)collectionView
{
    if (!_collectionView) {
        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        layout.itemSize = CGSizeMake(100, 100);
        layout.minimumLineSpacing = 10;
        layout.minimumInteritemSpacing = 10;
        _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(10, 100, 300, 600) collectionViewLayout:layout];
        [_collectionView registerClass:[PerformBatchCell class] forCellWithReuseIdentifier:@"cell"];
        [_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];
        _collectionView.delegate = self;
        _collectionView.dataSource = self;
    }
    return _collectionView;
}

- (UIButton *)firstButton
{
    if (!_firstButton) {
        _firstButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _firstButton.frame = CGRectMake(100, 100, 200, 100);
        _firstButton.titleLabel.font = [UIFont systemFontOfSize:14];
        _firstButton.backgroundColor = [UIColor redColor];
        [_firstButton setTitle:@"隐藏头部并reloadData" forState:UIControlStateNormal];
        [_firstButton addTarget:self action:@selector(firstClick) forControlEvents:UIControlEventTouchUpInside];
    }
    return _firstButton;
}

- (UIButton *)secondButton
{
    if (!_secondButton) {
        _secondButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _secondButton.frame = CGRectMake(100, 250, 200, 100);
        _secondButton.backgroundColor = [UIColor greenColor];
        [_secondButton setTitle:@"展示头部并performBatchUpdates" forState:UIControlStateNormal];
        [_secondButton addTarget:self action:@selector(secondClick) forControlEvents:UIControlEventTouchUpInside];
        _secondButton.titleLabel.font = [UIFont systemFontOfSize:14];

    }
    return _secondButton;
}

- (UIButton *)thirdButton
{
    if (!_thirdButton) {
        _thirdButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _thirdButton.frame = CGRectMake(100, 400, 200, 100);
        _thirdButton.backgroundColor = [UIColor blueColor];
        [_thirdButton setTitle:@"模拟加载上一页" forState:UIControlStateNormal];
        [_thirdButton addTarget:self action:@selector(loadPreviousPage) forControlEvents:UIControlEventTouchUpInside];
        _thirdButton.titleLabel.font = [UIFont systemFontOfSize:14];
    }
    return _thirdButton;
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

效果图
请添加图片描述


http://www.kler.cn/a/470908.html

相关文章:

  • Centos源码安装MariaDB 基于GTID主从部署(一遍过)
  • PySide6的样式表
  • C++ 中如何优雅地返回一个递归闭包函数?
  • [文献精汇]使用PyCaret预测 Apple 股价
  • Excel 做数据分析的好与不好
  • ComfyUI节点安装笔记
  • 分布式IO模块:激光切割机产线高效控制的创新引擎
  • c# 中Parallel.ForEach 对其中一个变量进行赋值 引发报错
  • 计算机网络•自顶向下方法:多址接入协议
  • 【AI数学基础】线性代数:向量空间
  • reactor的Hooks.enableAutomaticContextPropagation();不生效解决方案
  • 基于32单片机的智能语音家居
  • pytest日志显示
  • gesp(C++一级)(18)洛谷:B4063:[GESP202412 一级] 奇数和偶数
  • 某制造集团灯塔工厂解决方案(36页PPT)
  • 安装vue脚手架出现的一系列问题
  • 计算机网络——网络层—路由算法和路由协议
  • 感知器的那些事
  • springboot适配mybatis+guassdb与Mysql兼容性问题处理
  • 升级 Spring Boot 3 配置讲解 —— Spring Boot 3 核心源码专讲
  • 如何在 Ubuntu 22.04 上安装 Nagios 服务器教程
  • Flutter:打包apk,安卓版本更新(二)
  • 使用Python构建远程医疗平台:从零开始的实现指南
  • 【错误记录】HarmonyOS 编译报错 ( DevEco Studio 开发环境 与 API 版本 与 HarmonyOS 版本 的配套关系 )
  • 君正T41交叉编译ffmpeg、opencv并做h264软解,利用君正SDK做h264硬件编码
  • Angular由一个bug说起之十三:Cross Origin