iOS CollectionView FlowLayout與風火輪佈局 (二)
UICollectionView自定義佈局實現風火輪(Ray wenderlich上的教程
具體過程請看 Ray Wenderlich上的教程,網上也能找到其他開發者翻譯。這裡只記錄幾個我覺得比較重要的
對於自定義佈局,最主要的有三個函式:
- (void)prepareLayout
用於排列cell前,計算各個cell位置資訊,避免將cell加到 collectionview 上時臨時計算:
- 在collectionview第一次展現內容時呼叫
- 佈局更新時,呼叫此函式來準備好下一次的佈局
- (CGSize)collectionViewContentSize
collectionView可滑動的區間
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
返回一個可視rect範圍內被顯示cell的UICollectionViewLayoutAttributes
UICollectionViewLayoutAttributes
類管理了佈局相關的屬性,如cell的frame
、transform
、bounds
、zIndex
、center
等。它們的定義與用法與UIView
中各自屬性一致。
環形佈局
環形佈局最重要的一點就是,讓所有cell圍繞一個點轉起來。
關於view的旋轉,可以設定transform,讓view旋轉一定的角度。但是這樣,所有的view都是繞其center旋轉,不能達到我們的效果。
我們也可以設定anchorPoint
,因為所有關於view的幾何運算都與其有關。關於anchorPoint,看這篇文章
關於anchorPoint DEMO
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var anchorPointView: UIView!
var viewArray : [UIView] = []
var isMoved = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let tapGesture = UITapGestureRecognizer(target: self, action: "tap")
self.view.addGestureRecognizer(tapGesture)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
for i in (1...5) {
let eView = UIView(frame: self.anchorPointView.frame)
eView.backgroundColor = UIColor.blueColor()
viewArray.append(eView)
self.view.addSubview(eView)
}
}
func tap() {
//修改anchorPoint
self.anchorPointView.layer.anchorPoint = CGPointMake(0.5, 0.5 + 3.0)
//旋轉
anchorPointView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI / 10) * 0)
//修正view的位置
//因為修改了anchorPoint,而position不變,從而導致view上移300個點(anchorPointView 寬高都為100)
//300根據 (高100)*(anchorPoint在y上增加值3)
var center = self.anchorPointView.center
center.y += 300
self.anchorPointView.center = center
var i = 1.0
for view in viewArray {
view.layer.anchorPoint = CGPointMake(0.5, 0.5 + 3.0)
view.transform = CGAffineTransformMakeRotation(CGFloat(M_PI / 10 * i))
i += 1.0 * 1
var center = view.center
center.y += 300
view.center = center
}
}
}
自定義UICollectionViewLayoutAttributes
根據上面環形佈局,想要讓cell環形排列,必須知道cell的anchorPoint與 旋轉角度angle。
旋轉角度angle對應 UICollectionViewLayoutAttributes 的 transform
,而anchorPoint作為一個CALayer的屬性,在UICollectionViewLayoutAttributes沒有對應的屬性,但這裡需要讓cell知道自己的anchorPoint,才能讓其正確旋轉。這裡就需要自定義UICollectionViewLayoutAttributes。
使用自定義子類,與使用UICollectionViewLayoutAttributes相比,你需要增加一些程式碼。
- 在自定義佈局的相關實現中:
- (Class)layoutAttributesClass {
//返回自定義UICollectionViewLayoutAttributes子類
return [CircularCollectionViewLayoutAttributes class];
}
這樣每當需要生成一個新的LayoutAttributes object時就會呼叫此函式
2. 在需要顯示的 UICollectionViewCell的實現中
-
(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
[super applyLayoutAttributes:layoutAttributes];
if ([layoutAttributes isKindOfClass:[CircularCollectionViewLayoutAttributes class]]) {
CircularCollectionViewLayoutAttributes *attributes = (CircularCollectionViewLayoutAttributes *)layoutAttributes;CGPoint centerPoint = self.center; self.layer.anchorPoint = attributes.anchorPoint; centerPoint.y += self.selected? (attributes.anchorPoint.y - 0.5) * CGRectGetHeight(self.bounds) - 50: (attributes.anchorPoint.y - 0.5) * CGRectGetHeight(self.bounds); self.center = centerPoint;
}
}
這樣新增加的UICollectionViewLayoutAttributes屬性,才有機會作用在cell上
###佈局核心過程程式碼
-
(void)prepareLayout {
[super prepareLayout];
CGFloat centerX = self.collectionView.contentOffset.x + CGRectGetWidth(self.collectionView.bounds) / 2.0;
CGFloat anchorPointY = ((_itemSize.height / 2) + _radius ) / _itemSize.height;int startIndex = 0;
int endIndex = (int)[self itemCount] - 1;
// CGFloat theta = atan2(CGRectGetWidth(self.collectionView.bounds) / 2.0,
// _radius + (_itemSize.height / 2.0) - CGRectGetHeight(self.collectionView.bounds) / 2.0);
// if ([self angle] < -theta) {
//
// startIndex = (int)(floor( (-[self angle] - theta) / [self anglePerItem]));
//
// }
//
// endIndex = MIN(endIndex, (int)ceil((-[self angle] + theta) / [self anglePerItem]) );
//
// if (endIndex < startIndex) {
//
// startIndex = 0;
// endIndex = 0;
//
// }for (int i = startIndex; i <= endIndex; i++) {
CircularCollectionViewLayoutAttributes *attribute = [CircularCollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; attribute.size = _itemSize; attribute.center = CGPointMake(centerX, CGRectGetMidY(self.collectionView.bounds)); attribute.anchorPoint = CGPointMake(0.5, anchorPointY); attribute.angle = [self angle] + [self anglePerItem]*i; [_layoutAttributes addObject:attribute];
}
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
//返回prepareLayout計算好的佈局
return _layoutAttributes;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
//
return _layoutAttributes[indexPath.row];
}
-
(CGSize)collectionViewContentSize {
return CGSizeMake([self.collectionView numberOfItemsInSection:0] * _itemSize.width, CGRectGetHeight(self.collectionView.bounds));
}
-
(Class)layoutAttributesClass {
return [CircularCollectionViewLayoutAttributes class];
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
//每次滑動,都觸發新的佈局
return true;
}
相關文章
- CollectionView 佈局收集View
- 解析SwiftUI佈局細節(二)迴圈輪播+複雜佈局SwiftUI
- iOS - 二級連動(tableview包含 collectionview)iOSView
- Swift 專案總結 03 自定義 CollectionView 佈局SwiftView
- iOS CollectionView 的那些事iOSView
- Swift iOS : 使用Cartography佈局SwiftiOS
- iOS Flexbox 佈局優化iOSFlex優化
- 系統學習iOS動畫之二:自動佈局iOS動畫
- dispaly的Grid佈局與Flex佈局Flex
- iOS 常用佈局方式之ConstraintiOSAI
- css經典佈局系列二——等分等高佈局CSS
- CSS經典佈局——聖盃佈局與雙飛翼佈局CSS
- 聖盃佈局與雙飛翼佈局
- UICollectionView自定義佈局(二)UIView
- 網頁佈局------輪播圖效果實現網頁
- iOS自動佈局——Masonry詳解iOS
- iOS UICollectionView 橫向分頁佈局iOSUIView
- css居中與佈局CSS
- 自定義流式佈局:ViewGroup的測量與佈局View
- 【iOS】關於 UICollectionView 的自定義佈局iOSUIView
- setContentView與Activity初始佈局View
- CSS如何佈局與居中CSS
- HTML 標籤與佈局HTML
- Flutter基礎-009-Row水平佈局與Column垂直佈局Flutter
- 使用 Flex 佈局與其他普通佈局的簡單對比Flex
- iOS冰與火之歌 – UAF and Kernel PwniOS
- css佈局-float佈局CSS
- CSS佈局 --- 居中佈局CSS
- CSS常見佈局與居中CSS
- Flutter 佈局(二)- Padding、Align、Center詳解Flutterpadding
- java:佈局方法(流佈局)Java
- qt 佈局---表單佈局QT
- 居中佈局、三欄佈局
- JavaScript時間輪盤:js元素圓形佈局製作時間輪盤動畫JavaScriptJS動畫
- [開發教程]第6講:Bootstrap巢狀佈局與流動佈局boot巢狀
- 短視訊商城原始碼,首頁輪播圖佈局管理原始碼
- CSS佈局概念與技術教程CSS
- Flex佈局語法與實踐Flex
- Android 常用佈局 介紹與使用Android