Senior iOS development share – see UICollectionViewController (a)
Senior iOS development share – see UICollectionViewController (2)
Senior iOS development share – see UICollectionViewController (3)
IOS development develop the advanced share – see UICollectionViewController (4)
A cool picture browsing component
This blog is another example of using custom CollectionView. The method of custom CollectionView is the same as that in the previous article. It overwrites the methods of UICollectionViewLayout, and then sets the parameters of the layout through the delegate callback. The idea of customizing CollectionView is the same, but the implementation is different. CollectionView; CollectionView; CollectionView; CollectionView; CollectionView
Click here to get selected interview materials
1. Effect display
Without further ado, enter the theme of today’s blog, below is the running effect of Demo in today’s blog. Although the running effect made into GIF lost frame, it looks like some card, but it still runs smoothly. Make a 360-degree rotation when switching images and change the hierarchy of the Cell so that the current image is displayed at the highest level. And when moving, do a position correction if the image to be displayed is not in the center of the screen. When you click on an image, use an affine transform to enlarge it, and then click to shrink it. The implementation scheme will be introduced in detail next.
2. How to use the custom layout
Let’s take a look at how the custom layout is used and then walk through how it is implemented. It’s also a process that starts from the beginning, because it’s easier to use than to start. For example, driving a car is easy, but building a car is much more difficult. So in the second part of this blog, I’ll show you how to use this custom component.
The custom layout of all CollectionViews is used in the same way:
- This post’s CollectionView is implemented in Storyboard, so we can specify our custom layout file in Storyboard, if you’re using pure code, You can specify the desired layout at CollectionView instantiation time. Below is the Layout file that you want to specify using the Storyboard. You need to set the Layout option under Custom, and then the Class option below is the Custom Layout file that you want to associate, as shown below. Code on this do not repeat, a catch a lot of online.
- Associate a class with the CollectionViewController in our Storyboard, and then we can use our custom layout. Gets the specified custom layout object, and then specifies the delegate delegate object, as shown below:
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 4 _customeLayout = (CustomTransformCollecionLayout *) self.collectionViewLayout; 5 _customeLayout.layoutDelegate = self; 6}Copy the code
- In addition to implementing the DataSource and Delegate of the CollectionView, we also need to implement the Delegate methods of the layout. The first is to set the size of the Cell, that is, the width and height. The second is to set the margins between cells.
1 #pragma mark <CustomTransformCollecionLayoutDelegate>
2
3 - (CGSize)itemSizeWithCollectionView:(UICollectionView *)collectionView
4 collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout {
5 return CGSizeMake(200, 200);
6 }
7
8 - (CGFloat)marginSizeWithCollectionView:(UICollectionView *)collectionView
9 collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout {
10 return 10.0f;
11 }
Copy the code
- Click the Cell zoom in and out is click a Cell in the UICollectionViewDataSource agent method to do, here is no need to do, see lot sharing links.
Three. How to achieve
This explains how to use the custom component, and now it’s time to “build the car.” The third part of this blog describes how to implement this custom layout.
- CustomTransformCollecionLayout header file with the code as shown below, the file defines a protocol, the methods of the agreement is to realize the two agents in CollectionView method. These proxy methods provide the size and margins of the Cell. The interface to this file defines a proxy object, which is of type weak, of course, for strong reference loops.
1 // 2 // CustomTransformCollecionLayout.h 3 // CustomTransformCollecionLayout 4 // 5 // Created by Mr.LuDashi on 15/9/24.6 // Copyright (C) 2015 ZeluLi. All rights Reserved#import <UIKit/UIKit.h>10 of 11#define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width
12 #define SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height13 14 @class CustomTransformCollecionLayout; 15 to 16 @ protocol CustomTransformCollecionLayoutDelegate < NSObject > 17 18 * / * * 19 * / 20 - to determine the size of the cell (CGSize) itemSizeWithCollectionView:(UICollectionView *)collectionView 21 collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout; 22 23 / * * 24 * to determine the cell size 25 * / 26 - (CGFloat) marginSizeWithCollectionView collectionView 27: (UICollectionView *) collectionViewLayout:(CustomTransformCollecionLayout *)collectionViewLayout; 28 29 @end 30 31 @interface CustomTransformCollecionLayout : UICollectionViewLayout 32 33 @property (nonatomic, weak) id<CustomTransformCollecionLayoutDelegate> layoutDelegate; 34 35 @endCopy the code
- Next to introduce CustomTransformCollecionLayout implementation file is. M the code, including the extension of the attributes as shown below. NumberOfSections: this parameter represents the numberOfSections in the CollectionView. NumberOfCellsInSection: Specifies the number of cells in each Section. ItemSize is the size (width and height) of the Cell, and the value of this property is provided by the layout proxy method. ItemMargin: This property is the margin of the Cell, which is also provided through the layout’s proxy method. ItemsX: The X coordinate of each Cell used to store the computation.
1 // 2 // CustomTransformCollecionLayout.m 3 // CustomTransformCollecionLayout 4 // 5 // Created by Mr.LuDashi on 15/9/24.6 // Copyright (C) 2015 ZeluLi. All rights Reserved#import "CustomTransformCollecionLayout.h"10 11 @interface CustomTransformCollecionLayout() 12 13 @property (nonatomic) NSInteger numberOfSections; 14 @property (nonatomic) NSInteger numberOfCellsInSection; 15 @property (nonatomic) CGSize itemSize; 16 @property (nonatomic) CGFloat itemMargin; 18 @property (nonatomic, strong) NSMutableArray *itemsX; 19 20 @endCopy the code
- In the implementation we need to rewrite UICollectionViewLayout related methods, need to rewrite the method as follows:
(1). The preload layout method, which is executed once when the UICollectionView loads the data, is responsible for calling some initialization functions in this method. The details are as follows.
1 Pragma Mark -- UICollectionViewLayout overwrites the method2 - (void)prepareLayout { 3 [super prepareLayout]; 4 5 [self initData]; 6 7 [self initItemsX]; 8}Copy the code
(2). The following methods return ContentSize, specifically the size of the CollectionView scroll area.
1/2 * * * this method returns the size of the ContentSize CollectionView 3 * / 4 - (CGSize) collectionViewContentSize {5 CGFloat width = _numberOfCellsInSection * (_itemSize.width + _itemMargin); 6returnCGSizeMake(width, SCREEN_HEIGHT); 7}Copy the code
(3) for each Cell at the bottom of the method is binding a UICollectionViewLayoutAttributes object, used to set the properties of each Cell.
1/2 * * * the method for each Cell binding a Layout attribute ~ 3 * / 4 - (NSArray *) layoutAttributesForElementsInRect: (CGRect) the rect {5 6 NSMutableArray *array = [NSMutableArray array]; 7 8 //add cells 9for (int i = 0; i < _numberOfCellsInSection; i++) {
10 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; 11 12 UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath]; 13 14 [array addObject:attributes]; 15} 16returnarray; 17}Copy the code
(4). The method below is more important. This method is overwritten to set different attribute values for each Cell. The transform value is calculated according to the roll offset of the CollectionView, so when the CollectionView is rolled, the Cell will also rotate. The concrete implementation adds comments to the code, as shown below:
1/2 * * * set the attribute for each Cell 3 * / 4 - (UICollectionViewLayoutAttributes *) layoutAttributesForItemAtIndexPath: (NSIndexPath *) indexPath {5 6 / / get the attributes of the current Cell 7 UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 8 and 9 / / for sliding displacement 10 CGFloat contentOffsetX = self. CollectionView. ContentOffset. X. 12 NSInteger currentIndex = [self countIndexWithOffsetX: contentOffsetX]; 13 CGFloat centerX = [_itemsX[indexpath.row]floatValue]; 16 CGFloat centerY = SCREEN_HEIGHT/2; 17 18 // Set the center and size attributes of the Cell. 19 Attributes. Center = CGPointMake(centerX, centerY); 20 attributes.size = CGSizeMake(_itemSize.width, _itemSize.height); CGFloat animationDistance = _itemsize. width + _itemMargin; CGFloat animationDistance = _itemsize. width + _itemMargin; 24 CGFloat change = contentOffsetX - currentIndex * animationDistance + SCREEN_WIDTH / 2 - _itemSize.width / 2; 25 26 // Make a position correction, because when you slide by half, the currentIndex will increment by one, which is not the index of the Cell that was displayed last time, so subtract by one and make a correction 27if(change < 0) { 28 change = contentOffsetX - (currentIndex - 1) * animationDistance + SCREEN_WIDTH/2 - _itemSize.width/2; 29} 30 and 31if(currentIndex == 0 && contentOffsetX <= 0) { 32 change = 0; 33} 35 CGFloat temp = M_PI * 2 * (change/(_itemsize.width + _itemMargin)); 37, 38 / / affine transformation assignment 39 attributes. The transform = CGAffineTransformMakeRotation (temp); 40 41 // Set the zIndex of the currently displayed Cell to a larger value 42if(currentIndex == indexPath.row) { 43 attributes.zIndex = 1000; 44}else{ 45 attributes.zIndex = currentIndex; 46} 47 48returnattributes; 49}Copy the code
(5). To make the Cell scroll around, you need to override the following method and return YES. This method returns YES meaning that when scrolling, the method above (4) is executed again, reassigning the attributes of each Cell. So override the following method and return YES(same as the following expression) to get it moving.
1 // Whether the layout should be refreshed when boundaries change. If YES, the required layout information will be recalculated when the boundary changes (typically scroll to somewhere else). 2 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { 3return !CGRectEqualToRect(newBounds, self.collectionView.bounds);
4 }
Copy the code
(6). Rewrite the following method to correct the offset of the CollectionView scroll so that the currently displayed Cell appears in the center of the screen as follows:
1 // Fix Cell position, Make the current Cell is displayed in the center of the screen, 2 - (CGPoint) targetContentOffsetForProposedContentOffset: (proposedContentOffset CGPoint) WithScrollingVelocity :(CGPoint)velocity{3 4 5 NSInteger index = [self countIndexWithOffsetX:proposedContentOffset.x]; 7 8 CGFloat centerX = index * (_itemSize.width + _itemMargin) + (_itemSize.width/2); 9 10 proposedContentOffset.x = centerX - SCREEN_WIDTH/2; 11 to 12returnproposedContentOffset; 13}Copy the code
- Below is my own implementation of the method, also in the overridden method call function, as follows.
1 #pragma mark -- Custom methods4 */ 5 - (NSInteger) countIndexWithOffsetX: (CGFloat) offsetX{6return(offsetX + (SCREEN_WIDTH / 2)) / (_itemSize.width + _itemMargin); 7} 8 9 /** 10 Configuration parameters are obtained through agent 11 * / 12 - (void) initData {13 _numberOfSections = self. CollectionView. NumberOfSections; 14 15 _numberOfCellsInSection = [self.collectionView numberOfItemsInSection:0]; 16 17 _itemSize = [_layoutDelegate itemSizeWithCollectionView:self.collectionView collectionViewLayout:self]; 18 19 _itemMargin = [_layoutDelegate marginSizeWithCollectionView:self.collectionView collectionViewLayout:self]; 25 */ 26 - (void) initItemsX{27 _itemsX = [[NSMutableArray alloc] initWithCapacity:_numberOfCellsInSection]; 28, 29for(int i = 0; i < _numberOfCellsInSection; i ++) { 30 CGFloat tempX = i * (_itemSize.width + _itemMargin) + _itemSize.width/2; 31 [_itemsX addObject:@(tempX)]; 32} 33 34 35}Copy the code
What do you think? Please add our communication groupClick here to enter the communication groupTo communicate or post your questions, comments or feedback.
Github Demo link: github.com/lizelu/Cust…
Author: Qingyu Fu Case Source: www.cnblogs.com/ludashi/