iOS控件 -- UICollectionView (瀑布流)

2024-02-03 00:36

本文主要是介绍iOS控件 -- UICollectionView (瀑布流),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

iOS控件--UICollectionView (瀑布流)

  • 前言
  • 概念
    • UICollectionView的设计理念
    • UICollectionView的工作流程
  • 使用
    • collectionView重要的方法
    • 注意!!!
    • collectionView需要遵守的协议
      • UICollectionViewDelegate协议:
      • UICollectionViewDataSource协议
        • 必须实现的方法:
        • 可选实现的方法:
  • 示例
    • 九宫格
    • 瀑布流

前言

UICollectionView是一个功能十分强大的控件,用法上和UITableView比较相似。

概念

UICollectionView的设计理念

UICollectionView 是 iOS 开发中用于管理和展示一个可滚动的数据集合的一个非常强大的界面组件。它是在 iOS 6 中引入的,作为 UITableView 的一个更加灵活和扩展的版本,允许开发者以二维网格的形式展示项目,而不仅仅是 UITableView 的单一列。

UICollectionView的工作流程

当UICollectionView显示内容时,先从数据源获取cell,然后交给UICollectionView。再从UICollectionViewLayout获取对应的layout attributes(布局属性)。最后,根据每个cell对应的layout attributes(布局属性)来对cell进行布局,生成了最终的界面。而用户交互的时候,都是通过Delegate来进行交互。当然,上面只是布局cell,但是UICollectionView内部还有Supplementary View和Decoration View,也可以对其进行布局。

UICollectionView是比UITableView更加强大的控件,有如下几个方面:

  1. 支持水平和垂直两个方向上的布局
  2. 通过layout配置方式进行布局
  3. CollectionView中的item大小和位置可以自定义
  4. 通过layout布局回调的代理方法,可以动态的定制每一个item的大小和collection的大体布局属性
  5. 可以完全自定义一套layout布局方案,实现意想不到的效果

使用

collectionView重要的方法

初始化布局:

//layout布局类UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

设置布局是垂直还是水平:

//布局方向为垂直流布局layout.scrollDirection = UICollectionViewScrollDirectionVertical;

设置每个item的大小:

    //设置每个item的大小layout.itemSize = CGSizeMake(120, 100);

collectionView的初始化:

self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];

注册item类型:

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];

注意!!!

tableView的cell可以有注册和不注册两种方法,但是collectionView只能注册!!!

collectionView需要遵守的协议

collectionView需要遵守的协议和tableView差不多。

UICollectionViewDelegate协议:

是否允许某个item的高亮,返回NO,则不能进入高亮状态。- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath;当item高亮时触发的方法。- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath;结束高亮状态时触发的方法。- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath;是否可以选中某个item,返回NO,则不能选中- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;是否可以取消选中某个item- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;已经选中某个item时触发的方法- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;取消选中某个item时触发的方法- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;将要加载某个item时调用的方法- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);将要加载头尾视图时调用的方法。- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);已经展示某个item时触发的方法。- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;已经展示某个头尾视图时触发的方法。- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
UICollectionView进行重新布局时调用的方法- (nonnull UICollectionViewTransitionLayout *)collectionView:(UICollectionView *)collectionView transitionLayoutForOldLayout:(UICollectionViewLayout *)fromLayout newLayout:(UICollectionViewLayout *)toLayout;

以上协议都是可选实现的

UICollectionViewDataSource协议

必须实现的方法:

设置每个分区的item数:

//设置每个分区的item数:- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;

设置返回每个item的属性:

//设置返回每个item的属性:- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
可选实现的方法:
//设置分区数,虽然这个方法是可选的,一般我们都会去实现,不去设置它的话,它的默认值为1:- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;//对头视图或者尾视图进行设置- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;//设置某个item是否可以被移动,返回NO则不能移动- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
(void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath )sourceIndexPath toIndexPath:(NSIndexPath)destinationIndexPath;//移动item的时候,会调用这个方法
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath )sourceIndexPath toIndexPath:(NSIndexPath)destinationIndexPath;

示例

九宫格

#import "ViewController.h"#define WIDTH ([UIScreen mainScreen].bounds.size.width)
#define HEIGHT ([UIScreen mainScreen].bounds.size.height)@interface ViewController () <UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) UICollectionView* collectionView;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = UIColor.whiteColor;//layout布局类UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];//布局方向为垂直流布局layout.scrollDirection = UICollectionViewScrollDirectionVertical;//设置每个item的大小layout.itemSize = CGSizeMake(WIDTH / 3 - 10, WIDTH / 3 - 10);self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];//代理设置self.collectionView.delegate = self;self.collectionView.dataSource = self;//重点:必须进行注册!!!(重点中的重点,一旦注册出现错误,就会导致程序崩溃)[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];[self.view addSubview:_collectionView];
}//返回分区个数(这个方法并不一定要实现)
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {return 1;
}
//返回每个分区的item个数(但是这个方法一定要实现)
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {return 9;
}
//返回每个item
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];cell.backgroundColor = [UIColor colorWithRed:arc4random() % 255 / 255.0 green:arc4random() % 255 / 255.0 blue:arc4random() % 250 / 250.0 alpha:1];return cell;
}@end

在这里插入图片描述
我们这个设置的大小大约是屏幕三分之一,就会自动的三个item为一行

我们来改一下它的size:

layout.itemSize = CGSizeMake(200, 200);

在这里插入图片描述
就变成了两个item一行

例如九宫格的例子就可以应用于换头像功能,之前在写其他项目的换头像功能时,运用了循环创建button的方法,在学会了collectionView之后就变得简单了很多。

瀑布流

UICollectionView强大的一个原因,就是我们可以制作属于我们的布局,在我们平常刷一些app时,刷新加载的图片大小可能是不确定的,这是使用系统自带的布局是有局限的,所以我们可以自己去创造一个MyLayout类去实现它。
创建一个MyLayout类继承UICollectionViewFlowLayout.
简单来说,自定义一个FlowLayout布局类就是两个步骤:
1. 设计好我们的布局配置数据,prepareLayout方法中。
2. 返回我们的配置数组,layoutAttributesForElementsInRect方法中。

首先在MyFlowLayout文件中,定义好所需要的数据

#import "MyFlowLayout.h"@implementation MyFlowLayout{NSMutableArray * attributeArray; // frame 数组NSInteger _collectViewRowCount;  // 列数NSMutableArray * _originYAry;    //记录每一列的Y点坐标}- (instancetype)init
{self = [super init];if (self) {attributeArray = [NSMutableArray array];_originYAry = [NSMutableArray array];_collectViewRowCount = 2;}return self;
}- (void)prepareLayout{[attributeArray removeAllObjects];[_originYAry removeAllObjects];//初始化y坐标for (int i =0; i <_collectViewRowCount; i++) {[_originYAry addObject:@(0)];}//返回NSInteger cellCount = [self.collectionView numberOfItemsInSection:0];for (int i = 0; i < cellCount; i ++ ) {NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];//UICollectionViewLayoutAttributes 用于存储layout属性的对象UICollectionViewLayoutAttributes *attrib = [self layoutAttributesForItemAtIndexPath:indexPath];[attributeArray addObject:attrib];}
}//2.返回指定indexPath下的 UICollectionViewLayoutAttributes
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{//根据indexPath创建一个UICollectionViewLayoutAttributesUICollectionViewLayoutAttributes *layoutAttr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];//设置每个frameCGFloat width = [UIScreen mainScreen].bounds.size.width /_collectViewRowCount;CGFloat height = 50 + arc4random_uniform(20);CGFloat x = width * ( indexPath.row % _collectViewRowCount);CGFloat y = [_originYAry[indexPath.row % _collectViewRowCount] floatValue];_originYAry[indexPath.row % _collectViewRowCount] = @(height + y +10);layoutAttr.frame =CGRectMake(x, y, width, height);return layoutAttr;
}//3.返回collectionView的ContentSize
//由于瀑布流每一列的高度不一定,所以需要判读出最高的列作为height
-(CGSize)collectionViewContentSize{//kvc 获取最大值CGFloat maxY =[[_originYAry valueForKeyPath:@"@max.floatValue"] floatValue];return CGSizeMake([UIScreen mainScreen].bounds.size.width, maxY);
}//4.Returns the layout attributes for all of the cells and views in the specified rectangle.
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{return attributeArray;
}@end

然后在ViewController中进行调用。

MyFlowLayout* layout = [[MyFlowLayout alloc] init];layout.scrollDirection = UICollectionViewScrollDirectionVertical;self.collectionview = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];

在瀑布流的layout中:
1.可以设置collectionview的列数;
2.每个模块的宽和高;
3.不能确定每个分区的数量;

下面是代码的效果图:
在这里插入图片描述

这篇关于iOS控件 -- UICollectionView (瀑布流)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/672489

相关文章

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器

小程序button控件上下边框的显示和隐藏

问题 想使用button自带的loading图标功能,但又不需要button显示边框线 button控件有一条淡灰色的边框,在控件上了样式 border:none; 无法让button边框隐藏 代码如下: <button class="btn">.btn{border:none; /*一般使用这个就是可以去掉边框了*/} 解决方案 发现button控件有一个伪元素(::after

MFC中Spin Control控件使用,同时数据在Edit Control中显示

实现mfc spin control 上下滚动,只需捕捉spin control 的 UDN_DELTAPOD 消息,如下:  OnDeltaposSpin1(NMHDR *pNMHDR, LRESULT *pResult) {  LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR);  // TODO: 在此添加控件通知处理程序代码    if

MFC 控件重绘(2) NM_CUSTOMDRAW, WM_DRAWITEM, 虚函数DrawItem

控件重绘有三种方法: 1 设定界面属性 2 利用Windows的消息机制,通过Windows消息映射(Message Mapping)和反映射(Message Reflecting),在合适的时机修改控件的状态和行为。此方式涉及NM_CUSTOMDRAW和WM_DRAWITEM 3 利用虚函数机制,重载虚函数。即DrawItem虚函数。 对于NM_CUSTOMDRAW,某些支持此消息的控件

iOS剪贴板同步到Windows剪贴板(无需安装软件的方案)

摘要 剪贴板同步能够提高很多的效率,免去复制、发送、复制、粘贴的步骤,只需要在手机上复制,就可以直接在电脑上 ctrl+v 粘贴,这方面在 Apple 设备中是做的非常好的,Apple 设备之间的剪贴板同步功能(Universal Clipboard)确实非常方便,它可以在 iPhone、iPad 和 Mac 之间无缝传输剪贴板内容,从而大大提高工作效率。 但是,iPhone 如何和 Wind

C# 通过拖控件移动窗体

目录 引言一、通过控件事件移动窗体1、创建窗体界面2、添加控件事件3、添加代码 二、通过windowsAPI移动窗体1、 构建窗体和添加事件2、代码展示 引言 在C#Form窗体设计中,如果我们不需要使用默认边框设计自己个性化的窗体(FromBorderStyle=none时),这时候你会发现拖动窗体的功能就没有了,这里需要自己构建方法让用户可以拖动整个窗体,这里我们使用前辈的

Qt-常用控件(3)-多元素控件、容器类控件和布局管理器

1. 多元素控件 Qt 中提供的多元素控件有: QListWidgetQListViewQTableWidgetQTableViewQTreeWidgetQTreeView xxWidget 和 xxView 之间的区别,以 QTableWidget 和 QTableView 为例. QTableView 是基于 MVC 设计的控件.QTableView 自身不持有数据,使用 QTab

iOS项目发布提交出现invalid code signing entitlements错误。

1、进入开发者账号,选择App IDs,找到自己项目对应的AppId,点击进去编辑, 2、看下错误提示出现  --Specifically, value "CVYZ6723728.*" for key "com.apple.developer.ubiquity-container-identifiers" in XX is not supported.-- 这样的错误提示 将ubiquity