iOS之UICollectionView自定義佈局
UICollectionView基礎
- UICollectionViewFlowLayout:檢視佈局物件(流水佈局:一行排滿,自動排到下行),繼承自UICollectionViewLayout。UICollectionViewLayout內有一個collectionView屬性,所有的檢視佈局物件都繼承自UICollectionViewLayout。
- 若我們要自定義佈局物件,我們一般繼承UICollectionViewFlowLayout,然後重寫裡面的一些方法就可以了。
- 需要實現三個協議;UICollectionViewDataSource(資料來源)、UICollectionViewDelegateFlowLayout(檢視佈局),自定義佈局需要實現UICollectionViewDataSource、UICollectionViewDelegate兩個協議即可。
一、自定義線性佈局
- 首先要繼承與流水佈局UICollectionViewFlowLayout
#import <UIKit/UIKit.h>
@interface LineCollectionViewLayout : UICollectionViewFlowLayout
@end
- 重寫相應的方法
#import "LineCollectionViewLayout.h"
@implementation LineCollectionViewLayout
- (instancetype)init{
if (self = [super init]) {
}
return self;
}
/**
* 用來做佈局的初始化操作(不建議在init方法中進行佈局的初始化操作)
- 注意:一定要呼叫[super prepareLayout]
*/
- (void)prepareLayout{
[super prepareLayout];
// 水平滾動
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 設定內邊距
CGFloat inset = (self.collectionView.frame.size.width - self.itemSize.width) * 0.5 ;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
}
/**
* 這個方法的返回值是一個數組(數組裡面存放著rect範圍內所有元素的佈局屬性)
* 這個陣列中存放的都是UICollectionViewLayoutAttributes物件
* 這個方法的返回值決定了rect範圍內所有元素的排布(frame)*/
/**
UICollectionViewLayoutAttributes *attrs;
1.一個cell對應一個UICollectionViewLayoutAttributes物件
2.UICollectionViewLayoutAttributes物件決定了cell的frame
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
// 獲得super已經計算好的佈局屬性
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 計算collectionView最中心點的x值
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
// 在原有佈局屬性的基礎上,進行微調
for (UICollectionViewLayoutAttributes *attrs in array) {
// cell的中心點x 和 collectionView最中心點的x值 的間距
CGFloat delta = ABS(attrs.center.x - centerX);
// 根據間距值 計算 cell的縮放比例
CGFloat scale = 1 - delta / self.collectionView.frame.size.width;
// 設定縮放比例
attrs.transform = CGAffineTransformMakeScale(scale, scale);
}
return array;
}
/**
* 當collectionView的顯示範圍發生改變的時候,是否需要重新重新整理佈局
* 一旦重新重新整理佈局,就會重新呼叫下面的方法:
1.prepareLayout
2.layoutAttributesForElementsInRect:方法
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
/**
* 這個方法的返回值,就決定了collectionView停止滾動時的偏移量
* proposedContentOffset:原本情況下,collectionView停止滾動時最終的偏移量
* velocity:滾動速率,通過這個引數可以瞭解滾動的方向
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
// 計算出最終顯示的矩形框
CGRect rect;
rect.origin.y = 0;
rect.origin.x = proposedContentOffset.x;
rect.size = self.collectionView.frame.size;
// 獲得super已經計算好的佈局屬性
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 計算collectionView最中心點的x值
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
// 存放最小的間距值
CGFloat minDelta = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
minDelta = attrs.center.x - centerX;
}
}
// 修改原有的偏移量
proposedContentOffset.x += minDelta;
return proposedContentOffset;
}
@end
自定義環形佈局
- 同樣要繼承與流水佈局UICollectionViewFlowLayout
#import <UIKit/UIKit.h>
@interface CircleCollectionViewLayout : UICollectionViewFlowLayout
@end
- 重寫相應的方法
#import "CircleCollectionViewLayout.h"
@interface CircleCollectionViewLayout()
/** 佈局屬性 */
@property (nonatomic, strong) NSMutableArray *attrsArray;
@end
@implementation CircleCollectionViewLayout
/** 懶載入 */
- (NSMutableArray *)attrsArray
{
if (!_attrsArray) {
_attrsArray = [NSMutableArray array];
}
return _attrsArray;
}
- (void)prepareLayout
{
[super prepareLayout];
[self.attrsArray removeAllObjects];
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (int i = 0; i < count; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.attrsArray addObject:attrs];
}
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
return self.attrsArray;
}
/**
* 這個方法需要返回indexPath位置對應cell的佈局屬性
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger count = [self.collectionView numberOfItemsInSection:0];
CGFloat radius = 70;
// 圓心的位置
CGFloat oX = self.collectionView.frame.size.width * 0.5;
CGFloat oY = self.collectionView.frame.size.height * 0.5;
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.size = CGSizeMake(50, 50);
if (count == 1) {
attrs.center = CGPointMake(oX, oY);
} else {
CGFloat angle = (2 * M_PI / count) * indexPath.item;
CGFloat centerX = oX + radius * sin(angle);
CGFloat centerY = oY + radius * cos(angle);
attrs.center = CGPointMake(centerX, centerY);
}
return attrs;
}
@end
對自定義佈局的使用
// 建立佈局
CircleCollectionViewLayout *layout = [[CircleCollectionViewLayout alloc] init];
// 建立CollectionView
CGFloat collectionW = self.view.frame.size.width;
CGFloat collectionH = 200;
CGRect frame = CGRectMake(0, 150, collectionW, collectionH);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
collectionView.dataSource = self;
collectionView.delegate = self;
[self.view addSubview:collectionView];
self.collectionView = collectionView;
// 註冊
[collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([PhotoCell class]) bundle:nil] forCellWithReuseIdentifier:photoId];
```
- ****增加 touchesBegan:方法,通過點選讓兩種佈局相互轉換****
```objc
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.collectionView.collectionViewLayout isKindOfClass:[LineCollectionViewLayout class]]) {
[self.collectionView setCollectionViewLayout:[[CircleCollectionViewLayout alloc] init] animated:YES];
} else {
LineCollectionViewLayout *layout = [[LineCollectionViewLayout alloc] init];
layout.itemSize = CGSizeMake(100, 100);
[self.collectionView setCollectionViewLayout:layout animated:YES];
}
}
相關推薦
iOS之UICollectionView自定義佈局
UICollectionView基礎 UICollectionViewFlowLayout:檢視佈局物件(流水佈局:一行排滿,自動排到下行),繼承自UICollectionViewLayout。UICollectionViewLayout內有一個collec
iOS開發之窺探UICollectionViewController(三) :使用UICollectionView自定義瀑布流
上篇部落格的例項是自帶的UICollectionViewDelegateFlowLayout佈局基礎上來做的Demo, 詳情請看《iOS開發之窺探UICollectionViewController(二) –詳解CollectionView各種回撥》。UICollectionV
【iOS】UICollectionView自己定義Layout之蜂窩布局
with top http reserve src 布局 step object .com 網上的UICollectionView的Layout布局,其cell的形狀多為矩形和圓形。 本篇博文將正六邊形作為cell的基本形狀,為您展現獨特的蜂窩布局效果及實現源代碼。 幫
Android學習筆記之為Dialog自定義佈局,並說明空指標問題
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
Android 之自定義佈局(繼承控制元件)
就是繼承已有的控制元件,建立新控制元件,保留繼承的父控制元件的特性,並且還可以引入新特性。下面就以支援橫向滑動刪除列表項的自定義ListView的實現來介紹。 1、建立刪除按鈕佈局delete_btn.xml,這個佈局是在橫向滑動列表項後顯示的: <?xml version="1.0" en
自定義ViewGroup之自定義佈局的實現
圖片預覽 1. 分析 1. 自定義簡易FrameLayout 分別左上,右上,左下,右下4個子View 2. 自定義簡易LinearLayout,實現橫向和縱向佈局 3. 自定義簡易RelativeLayout,實現layout_alignParen
iOS開發之Xcode自定義程式碼塊遷移
本文介紹了程式碼塊遷移的過程. 背景:由於最近換了新的mac,所以,要做自定義程式碼塊的遷移. 一.Xcode中的程式碼塊. 二.開啟 Finder,快捷鍵Command +
iOS開發之UITableView自定義Header檢視和自定義Footer檢視
//自定義Header檢視 - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInte
UICollectionView的自定義佈局
UICollectionView控制元件的使用一般會在特殊的介面處理上,但是也有比較規矩的應用軟體會用UICollectionView。例如效果如下的介面; 下面開始講述我的介面是如何做的。 1.首先我會把介面分成5個section,這就需要上篇文章講述
JEPLUS之APP自定義插件——JEPLUS軟件快速開發平臺
otto fff 使用 jid editor style img circle ckeditor JEPLUS之APP自定義插件 在JEPLUS中我們可以創建APP,但是創建的APP都是依賴於平臺功能在我們業務中有些需求並不是都要按照平臺
數據庫系列之mysql 自定義函數function,函數和存儲過程的區別
0.11 必須 def cte fec return語句 cit 新的 too mysql 自定義函數function,函數和存儲過程的區別 https://blog.csdn.net/u010365819/article/details/80470448 1.MySQL自
Log4Net 之將自定義屬性記錄到文件中 (三)
hive days bsp 文本 處理 message homepage layout backup 即解決了將自定義屬性記錄到數據庫之後。一個新的想法冒了出來,自定義屬性同樣也能記錄到文件中嗎?答案是肯定的,因為Log4Net既然已經考慮到了數據庫記錄方式,當然也一定考慮
小程式學習之旅----自定義元件toast例項
components目錄下新建資料夾toast,新建component,之後修改toast.js和toast.wxml <!--components/toast/toast.wxml--> <view class='wx_toast_container' hidden="{{!
非常實用的自定義佈局,自定義顯示時長的頂部toast
最近在工作中需要彈出頂部toast且顯示時間不固定。從而寫了下面的一個模擬toast的動畫: 先看動畫: public void isShowToast(final boolean isShow,View mToastV) { final int marinTop = 0;//距離頂
009-Ambari二次開發之新增自定義元件Redis(二)
上一篇我們主要介紹了Ambari新增元件的答題流程並以REDIS為例說明了流程,本篇在上一篇的基礎上,進一步完善說明流程並介紹如何給元件新增metric 掃描二維碼,關注BearData,獲取最新文章 上篇中,我們已經制作出了redis的rpm包,並重新編譯了我們修改後的Ambar
008-Ambari二次開發之新增自定義元件Redis(一)
Ambari目前支援的元件有HDFS、YARN、HBase、Hive、Pig、ZooKeeper、Sqoop、Storm、Flume、Tez、Oozie、Falcon、Storm、Altas、Knox、Spark、Ranger、Mahout、Kerberos等,已經涵蓋了從大資料應用的
車機開發之新增自定義鍵
S700平臺即安卓5.1.1系統新增額外的自定義鍵值按鍵: 在Android的原生系統中鍵值預設情況下是92個,從0-91;一般情況下,這些鍵值是夠用的,但是如果想擴充的話,還是需要新增新的鍵值的;像我們做車機專案的,新增新按鍵鍵值太易見了,比如將倒車檢測做成新自定義鍵值按鍵,我們需要到多個
javaweb之EL自定義函式
1.什麼是EL自定義函式 EL自定義函式是在EL表示式中呼叫的某個java類的靜態方法,這個靜態方法需在web應用程式中進行配置才可以被EL表示式呼叫。EL自定義函式可以擴充套件EL表示式的功能,讓EL表示式完成普通java程式程式碼所能完成的功能。 2.EL自定義函式開發步驟 編寫EL自定義函式
Xamarin自定義佈局系列——瀑布流佈局
原文: Xamarin自定義佈局系列——瀑布流佈局 Xamarin.Forms以Xamarin.Android和Xamarin.iOS等為基礎,自己實現了一整套比較完整的UI框架,包含了絕大多數常用的控制元件,如下圖 雖然XF(Xamarin.Forms簡稱XF,下同)為我們提供大這麼多的控制元件,但在
Xamarin自定義佈局系列——ListView的一個自定義實現ItemsControl(橫向列表)
原文: Xamarin自定義佈局系列——ListView的一個自定義實現ItemsControl(橫向列表) 在以前寫UWP程式的時候,瞭解到在ListView或者ListBox這類的列表空間中,有一個叫做ItemsPannel的屬性,它是所有列表中子元素實際的容器,如果要讓列表進行橫向排列,只需要在Xam