1. 程式人生 > >對collectionView切換不同layout,實現不同的layout佈局

對collectionView切換不同layout,實現不同的layout佈局

轉自: https://www.jianshu.com/p/539ef116c525

由於專案需求,需要在同一個collectionView上面,實現不同的layout佈局。一個是固定item大小,沒有動畫的layout,這個用UICollectionViewFlowLayout就可以實現;另一種是實現水平佈局,中間放大,能夠看見兩邊item邊緣的效果。

基於以上需求,在對第一個佈局,我直接設定一下UICollectionViewFlowLayout物件的itemSize就可以完成。但是對於第二種的水平移動中間放大的效果,需要自定義layout。下面我就詳細的敘述一下,我在自定義layout時,遇到的坑。

在自定義UICollectionViewFlowLayout的過程中,需要重寫三個方法:

1.- (void)prepareLayout;主要用於相關引數的初始化,比如itemSize,minimumLineSpacing,minimumInteritemSpacing,setScrollDirection(設定滾動方向,sectionInset(整個組的四周邊距);

/**

*實現一些初始化工作

*/

- (void)prepareLayout{

lastOffset = self.collectionView.contentOffset.x;

//設定每一個cell的尺寸

float itemWidth = SCR_WIDTH - 134;

//設定每一個cell的尺寸

self.itemSize = CGSizeMake(itemWidth, getCellHeight(itemWidth));

self.minimumLineSpacing = 38;

//滑動方向

[self setScrollDirection:UICollectionViewScrollDirectionHorizontal];

CGFloat inset = (self.collectionView.width - itemWidth) / 2.0;

//把item的左右邊切掉,讓item處在螢幕中間位置

//  UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right)

self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);

}

在這方法中,一定要注意設定sectionInset,因為它決定了你橫向移動首位item的位置。我在一開始,當你發現第一個位置,和最後一個位置,不是自己想要的,你就要開始從這個地方入手考慮了。

2.- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;這個方法是獲取所有item的layoutAttributes;

/** 

* 所有item的佈局屬性 

*/

- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{

//計算可見的矩形框

CGRect visiableRect;

visiableRect.size = self.collectionView.frame.size;

visiableRect.origin = self.collectionView.contentOffset;

//1.取得cell原來的UICollectionViewLayoutAttributes

NSArray *array = [super layoutAttributesForElementsInRect:rect];

//螢幕中間的X

CGFloat screenCenterX = self.collectionView.contentOffset.x + self.collectionView.width/2.0;

//2.遍歷所有的佈局屬性

[array enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

if (CGRectIntersectsRect(visiableRect, obj.frame)) {

//每個item的centerX

CGFloat itemCenterX = obj.center.x;

//差距越小,縮放越大

//計算縮放比例

CGFloat scale = 1 + 0.25 * (1 - ABS(itemCenterX - screenCenterX) / (self.collectionView.width/2));

obj.transform3D = CATransform3DMakeScale(scale, scale, 1);

}

}];

return array;

}

在這個方法中,可以獲取當前螢幕顯示的顯示的item,也就是視覺上所看到,從而找到需要做動畫的item

3.- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity。這個方法是獲取滑動停止的位置,根據我的需求,我需要在停止的時候,找到離螢幕中間最近的item,並將它顯示在螢幕中間。程式碼如下:

/** 

*用來設定collectionView停止滾動的那一刻的位置 proposedContentOffset: collectionView停止滾動的位置 velocity : 滾動速度 

*/

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{    // 判斷是否為第一個    if (proposedContentOffset.xself.collectionViewContentSize.width-SCR_WIDTH*1.5+self.sectionInset.right) {

return CGPointMake(self.collectionViewContentSize.width-SCR_WIDTH, 0);

}

//1.獲取collectionView最後停留的範圍

CGRect lastRect;

lastRect.origin = proposedContentOffset;

lastRect.size = self.collectionView.frame.size;

//2.取出這個範圍類所有佈局屬性

NSArray *array = [self layoutAttributesForElementsInRect:lastRect];

//3.遍歷所有佈局的屬性

//停止滑動時item應該在的位置

__block CGFloat adjustOffsetX = MAXFLOAT;

//螢幕中間的X

CGFloat screenCenterX = proposedContentOffset.x + self.collectionView.width/2.0;

[array enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

if (ABS(obj.center.x - screenCenterX) < ABS(adjustOffsetX)) {

adjustOffsetX = obj.center.x - screenCenterX;

}

}];

return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y);

}

以上3個方法,可以基本完成一個水平滑動的中間放大的layout的要求,在對兩個layout的切換,只需要設定setCollectionViewLayout:方法就行了。對於我現在的任務來說,我目前無法完成,滑動速度的控制。



作者:EmptyWalker
連結:https://www.jianshu.com/p/539ef116c525
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

相關推薦

collectionView切換不同layout,實現不同layout佈局

轉自: https://www.jianshu.com/p/539ef116c525 由於專案需求,需要在同一個collectionView上面,實現不同的layout佈局。一個是固定item大小,沒有動畫的layout,這個用UICollectionViewFlowLay

根據不同域名實現數據源切換

defs exclude gets ins else 數據庫切換 esp super local 最近在做項目合並,之前排隊項目(子項目)從idm項目(父項目)分開的,考慮的是獨立開發,但開發到後面太多依賴idm這邊,所以現在又要合並。。。。 子項目這邊有個saas模塊,主

js閉包例子—不同物件實現點贊累加

要點: 1.js中的閉包有兩種,一種是函式模式閉包,此例項就是這個模式,並且一般這種模式會有返回處理函式,需要快取的值,在返回處理函式才能實現快取資料,而延長作用域鏈的作用一半定義的是匿名函式。 2.大部分情況下函式模式閉包有返回值,如有返回值不能直接呼叫,需要接收函式。 3.這裡的點贊

Nuxt pages下不同的頁面對應layout下的頁面佈局

有時候我們pages中不同的頁面需要不同的個性化佈局這時候layout就起作用了 layouts 根目錄下的所有檔案都屬於個性化佈局檔案,可以在頁面元件中利用 layout 屬性來引用。 請確保在佈局檔案裡面增加 <nuxt/> 元件用於顯示頁面非佈局內容。

關於"一個作業系統下如何安裝多個不同版本的JDK?"、並實現不同版本之間的相互切換使用

本文章將教你如何在一個作業系統下安裝多個不同版本的JDK, 並且實現不同版本直接的相互切換使用。 JDK的各個版本如下:  由於以前我們總是習慣直接在Oracle官網上找到所需的版本進行直接下載JDK, 但是筆者我今天也是埋頭直接去了官網, 奈何Oracle官方已經限制了

springboot不同環境,不同配置的實現(開發環境和生產環境的切換

首先,是我實現的最終效果圖可以看到這裡配置了3個application,其中第一個是總的配置,第二個是開發環境,第三個是生產環境。總的配置總是會生效的,而另外兩個配置生效的條件,則要看看我們在總的配置裡配置了什麼,比如這裡,我在application.yml裡配置了開發環境s

MySQL中MyISAM和InnoDBB-Tree索引不同實現方式

索引是 MySQL資料庫很重要的一部分,它對資料表查詢效能的好壞起著決定性的作用,對大表尤甚。 作為索引中最為常見的一種型別,B-Tree索引大都採用的是 B+Tree資料結構來儲存資料(NDB叢集儲存引擎內部實際上採用 T-Tree結構儲存這種索引)。B-T

使用 curl() 函數實現不同站點之間註冊用戶的同步

return pla ie 10 erro close header 實現 bst none 一 需求 在A站點註冊一個新用戶,那麽,在B站點也會被同時註冊 二 思路 在A站點註冊的同時,調用API接口實現在B站點也會被同時註冊 三 實現 主要代碼如下: 1 func

ListView實現不同布局的顯示

null str 技術 cati 技術分享 返回 int blog get ListView進行不同布局的顯示,就需要重寫5種方法,本文以兩種布局為例 。 利用假數據進行模擬: 添加適配器 class MyBaseAdapter extends BaseAdapter{

Python實現不同格式打印九九乘法表

語法 pytho 內容 基本語法 復制 strong 希望 不同 itl 前言:最近在學習Python,學習資源有慕課網上的視頻教程、菜鳥教程以及Python官方文檔tutorial。雖然了解了Python的基本語法,但是還沒有真正意義上輸出自己寫的代碼。代碼小白,之前僅學

實現點擊圖片不同區域響應不同的事件

位置 轉換 unit 點擊 yun 單元 cgpoint use float 最近有一個遙控器的項目, 需要實現點擊圖片上指定位置響應不同事件 圖片如下: 大概目的是點擊圖片上的溫度可以直接改變空調溫度 大概思路就是先通過gesture獲取點擊的點坐標, 然後對坐標做處

Android橫豎屏切換View設置不同尺寸或等比例縮放的XML解決方案

fill 文件結構 nts mas hang 同名 log lan spa 在一些應用中,涉及到橫豎屏切換,View要切換成不同大小比例尺寸。為解決這種開發場景,有多種解決方案,比如可以重寫View,實現橫豎切換在onMesure或者此類View的回調方法裏面重新測量重新繪

背景圖片利用backgrond-posintion屬性實現不同形式的分割

utf title borde images set absolut font 圖片 charset <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> &

實現不同分辨率下高度自適應

tex 微軟雅黑 java utf har -c 自適應 height ont html: <!DOCTYPE html> <html> <head> <meta charset="UTF-8">

實現不同的用戶登錄到主界面後顯示不同的功能——權限管理

需要 tle 有一個 sta vertica font eth rules sql 登陸頁面 2.php 1 <title>無標題文檔</title> 2 </head> 3 4 <body>

Spring Boot+Profile實現不同環境讀取不同配置

images alt quest color ive 作用 讀取 ron 總結 文件結構如下: 但是官方推薦放在config文件夾下。 作用: 不同環境的配置設置一個配置文件,例如:dev環境下的配置配置在application-dev.properties中。p

如何實現不同交換機上的終端在同一VLAN上互聯?

vlan如何實現不同交換機上的終端在同一VLAN上互聯?如下圖: PC0,PC1和PC4在同一VLAN ,PC2和PC3在同一VLAN,怎麽實現同一VLAN 上的終端互通呢? 我們知道在交換機不做任何配置的時候,所有端口都在同一個默認vlan下,所以將終端配置好IP地址之後5臺PC就可以互通,但是現

不同終端實現自動跳轉到相應頁面的js代碼

get cati string type clas 實現 www oca pac 1 2 3 4 <script type="text/javascript"> if(/Android|webOS|iPhone|iP

多層交換機 實現不同網段 互通 思路解析

多層交換機 vlan 實驗名稱:多層交換機 實現不同網段 互通 思路解析實驗需求: ⑴ 三層交換 1,2,3,4 分別是vlan10,20,30,40的網關 (網關IP - 192.168.X.250/24) vlan 10 192.1

通過   一個多層交換機 實現 不同網段主機 互通

多層交換機 不同網段通信 vlan 實驗名稱:通過一個多層交換機實現不同網段主機互通實驗需求: 1、創建VLAN10\20\30,配置對應的IP地址; 2、配置交換機之間的trunk鏈路:SW1-SW2是手動,SW2-SW3是自動; 3、交換機之間的