UICollectionView 不会在屏幕旋转时更新其布局
Posted
技术标签:
【中文标题】UICollectionView 不会在屏幕旋转时更新其布局【英文标题】:UICollectionView Will Not Update Its Layout On Screen Rotation 【发布时间】:2018-02-15 19:41:34 【问题描述】:我有一个自定义的UIView
和一个UICollectionView
。
在屏幕旋转时,我试图让UICollectionView
在屏幕上伸展,然后重绘其单元格。
下载数据后,我尝试了[grid setNeedsLayout]
和[grid setNeedsDisplay]
,但都没有成功。
这就是我想要发生的事情:
肖像
风景
(这也是应用以横向启动时的显示方式,但如果您更改为纵向,它不会更新。)
但是如果我从Portrait
模式开始并切换到Landscape
,这就是我得到的。
我正在以编程方式创建这些视图。我没有使用任何情节提要。
我试过了:
-(void)viewDidLayoutSubviews
grid = [[MyThumbnailGridView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height/2, self.view.frame.size.width, self.view.frame.size.height/2)];
我也试过玩弄:
- (void) viewWillLayoutSubviews
UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
//LANDSCAPE
if(grid)
NSLog(@"Grid Needs Landscape Layout");
grid.frame =CGRectMake(0, self.view.frame.size.height/2, self.view.frame.size.width, self.view.frame.size.height/2);
[grid refreshData];
else
//PORTRIAT
if(grid)
NSLog(@"Grid Needs Portrait Layout");
grid.frame =CGRectMake(0, self.view.frame.size.height/2, self.view.frame.size.width, self.view.frame.size.height/2);
[grid refreshData];
但我无法拉伸。
有什么帮助吗?
MyThumbnailGridView
@interface ViewController () <UINavigationControllerDelegate>
MyThumbnailGridView *grid;
NSMutableArray * arrImages;
- (void)viewDidLoad
[super viewDidLoad];
arrImages = [NSMutableArray new];
grid = [[MyThumbnailGridView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height/2, self.view.frame.size.width, self.view.frame.size.height/2)];
//grid = [[MyThumbnailGridView alloc] initWithFrame:CGRectZero];
NSLog(@"showThumbnailGrid Grid View Size: %@", NSStringFromCGRect(grid.frame));
[self.view addSubview:grid];
[self getListOfImages];
-(void) getListOfImages
//Do background task to get images and fill arrImages
[self onDownloadImageDataComplete];
- (void) onDownloadImageDataComplete
grid.imageDataSource = arrImages;
// [grid setNeedsLayout];
// [grid setNeedsDisplay];
//...
@end
*MyThumbnailGridView.h
@interface MyThumbnailGridView : UIView
-(id)initWithFrame:(CGRect)frame;
-(void) refreshData;
@property (nonatomic,strong) NSArray *imageDataSource;
@end
*MyThumbnailGridView.m
@interface MyThumbnailGridView () <UICollectionViewDelegate, UICollectionViewDataSource>
UICollectionView *collectionView;
@end
@implementation MyThumbnailGridView
- (instancetype) initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if(self)
[self customInit];
return self;
- (void) customInit
collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:[[MyFlowLayout alloc] init]];
collectionView.delegate = self;
collectionView.dataSource = self;
collectionView.allowsMultipleSelection = NO;
collectionView.showsVerticalScrollIndicator = YES;
[collectionView setBackgroundColor:[UIColor darkGrayColor]];
[collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"MyId"];
[self addSubview:collectionView];
- (void) refreshData
NSLog(@"Refresh Grid Data");
[collectionView reloadData];
////other code
@end
MyFlowLayout
@interface MyFlowLayout : UICollectionViewFlowLayout
@end
@implementation MyFlowLayout
- (instancetype)init
self = [super init];
if (self)
self.minimumLineSpacing = 1.0;
self.minimumInteritemSpacing = 1.0;
self.scrollDirection = UICollectionViewScrollDirectionVertical;
return self;
- (CGSize)itemSize
NSInteger numberOfColumns = 3;
CGFloat itemWidth = (CGRectGetWidth(self.collectionView.frame) - (numberOfColumns - 1)) / numberOfColumns;
return CGSizeMake(itemWidth, itemWidth);
@end
MyCollectionViewCell
@interface MyCollectionViewCell : UICollectionViewCell
@property (strong, nonatomic) UIImageView *imageView;
@end
@implementation MyCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
self.imageView = [UIImageView new];
[self.imageView setContentMode:UIViewContentModeScaleAspectFill];
[self.imageView setClipsToBounds:YES];
[self.imageView setBackgroundColor:[UIColor darkGrayColor]];
[self.contentView addSubview:self.imageView];
return self;
- (void)prepareForReuse
[super prepareForReuse];
self.imageView.image = nil;
[self.imageView setHidden:NO];
- (void)layoutSubviews
[super layoutSubviews];
[self.imageView setFrame:self.contentView.bounds];
@end
【问题讨论】:
您可以尝试将viewWillLayoutSubviews
中的所有内容放入viewDidLayoutSubviews
,然后在该方法中先调用super.viewDidLayoutSubviews() 吗?
刚刚在 ViewController 中尝试过,没有用。
您应该使集合视图上的布局无效
@user-44651 你在第一行打过[super viewDidLayoutSubviews];
吗?
【参考方案1】:
这可以解决
您可以在方向的委托函数中更改MyThumbnailGridView
视图的框架,或者使用这样的约束创建视图
(void)viewDidLoad
[super viewDidLoad];
arrImages = [NSMutableArray new];
grid = [[MyThumbnailGridView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height/2, self.view.frame.size.width, self.view.frame.size.height/2)];
[self.view addSubview:grid];
[self getListOfImages];
-(void)viewDidLayoutSubviews
if(Once)
Once = NO;
// adding constraints
MyThumbnailGridView.translatesAutoresizingMaskIntoConstraints = NO;
[self.MyThumbnailGridView.widthAnchor constraintEqualToConstant:self.view.frame.size.width].active = YES;
[self.MyThumbnailGridView.heightAnchor constraintEqualToConstant:self.view.frame.size.height/2].active = YES;
[self.MyThumbnailGridView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
[self.MyThumbnailGridView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:self.view.frame.size.height/2].active = YES;
也实现这个
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
[self.view layoutIfNeeded];
[MyThumbnailGridView.collectionView invalidate];
// Do view manipulation here.
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
【讨论】:
那是斯威夫特。我正在使用 Obj-C 那也没用。【参考方案2】:问题在于,当应用旋转时,集合视图本身并没有改变大小。你已经给集合视图一个固定的frame
,然后就走开了。所以它永远不会改变。所以永远不要再摆出自己的样子。
您应该将 MyThumbnailGridView 及其集合视图子视图 autolayout 约束 赋予它们的父视图,以便它们在应用旋转时正确更改大小。
【讨论】:
以上是关于UICollectionView 不会在屏幕旋转时更新其布局的主要内容,如果未能解决你的问题,请参考以下文章
屏幕旋转后如何在 UICollectionView 中跟踪单元格的移动
设备旋转时如何自动调整 UICollectionView 的大小?
UICollectionView invalidateLayout 不会在屏幕方向更改时触发 sizeForItem