Ios 如何定义旋转时CollectionView的大小
我有一个带有2个CollectionView控制器的viewcontroller 我希望在旋转时,只有一个集合视图调整为自定义大小,而另一个视图保持不变 我尝试使用:Ios 如何定义旋转时CollectionView的大小,ios,objective-c,xcode,uicollectionview,Ios,Objective C,Xcode,Uicollectionview,我有一个带有2个CollectionView控制器的viewcontroller 我希望在旋转时,只有一个集合视图调整为自定义大小,而另一个视图保持不变 我尝试使用: - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Adjust cell size for orientation
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
return CGSizeMake(170.f, 170.f);
}
return CGSizeMake(192.f, 192.f);
}
但是,这只会更改两个CollectionView。如何使它只针对一个集合?我通过检测
setBounds:
方法中的方向变化来处理这个问题。我们对UICollectionView
进行子类化,并覆盖setBounds:
方法(见下文)。在flowLayoutForGallerySize
中,我们创建了一个新的UICollectionViewFlowLayout
,根据集合视图的大小使用不同的间距和itemSize
- (void)setBounds:(CGRect)bounds
{
// detect orientation changes and update itemSize in the flow layout
CGSize oldSize = self.bounds.size;
[super setBounds:bounds];
BOOL wasLandscape = (oldSize.width > oldSize.height);
BOOL nowLandscape = (bounds.size.width > bounds.size.height);
if (wasLandscape != nowLandscape) {
// create a new flow layout object for the new gallery size
self.flowLayout = [self flowLayoutForGallerySize:bounds.size];
// change to the new flow layout
[self setCollectionViewLayout:self.flowLayout animated:NO];
DLog(@"orientation change to %@", NSStringFromCGSize(bounds.size));
}
}
您可以更改if语句。您需要有对集合视图的引用
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && collectionView == self.firstCollectionView) {
return CGSizeMake(170.f, 170.f);
}
这是我的2美分-因为您的物品大小是静态的,为什么不在
collectionViewLayout
上设置物品大小
这样做比期望集合视图为每个单元格调用其委托方法更快
viewWillLayoutSubview
可用于检测视图控制器上的旋转。
invalidateLayout
可用于集合视图布局,以强制其重新准备布局,从而在这种情况下使其使用新尺寸定位图元
- (void)viewWillLayoutSubviews;
{
[super viewWillLayoutSubviews];
UICollectionViewFlowLayout *flowLayout = (id)self.firstCollectionView.collectionViewLayout;
if (UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) {
flowLayout.itemSize = CGSizeMake(170.f, 170.f);
} else {
flowLayout.itemSize = CGSizeMake(192.f, 192.f);
}
[flowLayout invalidateLayout]; //force the elements to get laid out again with the new size
}
编辑:使用Swift2.0示例更新
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
return
}
if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
flowLayout.itemSize = CGSize(width: 170, height: 170)
} else {
flowLayout.itemSize = CGSize(width: 192, height: 192)
}
flowLayout.invalidateLayout()
}
从iOS 8开始使用新的API时,我正在使用: Swift 3:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateCollectionViewLayout(with: size)
}
private func updateCollectionViewLayout(with size: CGSize) {
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode
layout.invalidateLayout()
}
}
override func viewWillTransition(到大小:CGSize,带协调器:UIViewControllerTransitionCoordinator){
super.viewWillTransition(到:大小,带:协调器)
updateCollectionViewLayout(带:大小)
}
private func updateCollectionViewLayout(大小:CGSize){
如果让布局=collectionView.collectionViewLayout为?UICollectionViewFlowLayout{
layout.itemSize=(size.width
目标C:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self updateCollectionViewLayoutWithSize:size];
}
- (void)updateCollectionViewLayoutWithSize:(CGSize)size {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode;
[layout invalidateLayout];
}
-(void)视图将转换大小:(CGSize)带有转换协调器的大小:(id)协调器{
[super ViewWillTransitionSize:size with TransitionCoordinator:coordinator];
[自我更新CollectionViewLayoutWithSize:size];
}
-(void)updateCollectionViewLayoutWithSize:(CGSize)大小{
UICollectionViewFlowLayout*布局=(UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
layout.itemSize=(size.width
问题是,如何在SizeFormiteIndeXPath中分隔两个集合视图。
为什么不是这样
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if collectionView == firstCollectionView{
return CGSize(width: self.frame.width/3, height: 40)
}
else if collectionView == secondCollectionView{
return CGSize(width: self.frame.width, height: self.frame.height-2)
}
abort()
}
验证后的答案无效
问题-使viewWillLayoutSubviews()中的布局无效是一项繁重的工作。实例化ViewController时,viewWillLayoutSubviews()会被多次调用
我的解决方案(Swift)-将尺寸操纵嵌入UICollectionViewDelegateFlowLayout中
我通过检查设备的旋转,然后重新加载布局,解决了这个问题。检查屏幕大小并使用此大小显示我的手机
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
//get new width of the screen
screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
//if landscape mode
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
screenDivide = 5;
}
else
{
screenDivide = 3;
}
//reload the collectionview layout after rotating
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
[layout invalidateLayout];
}
然后我定义了这样的细胞
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
CGSize elementSize = CGSizeMake(screenWidth/screenDivide, 100);
return elementSize;
}
我发布的代码可以很好地调整大小,但是,我希望它只调整两个独立集合视图中的一个视图的大小,为什么不查看collectionView:参数以查看传入的是哪一个视图,并仅在其为正确的视图时应用它?这是可行的,但我现在收到一条警告,指出:不兼容的指针类型正在初始化“UICollectionViewFlowLayout*”类型为“UICollectionViewLayout*”的表达式您需要强制转换collectionViewLayout,我现在将调整答案@RobertFarr@OliverAtkinsontks。我的应用程序已经可以使用了。但在每个单元格中,我有一个imageview时会发生什么?在调整集合视图单元格的大小后,但图像未加载,我必须重新加载或向左/向右滑动以获得图像更新。如何更新/重新加载这些imageview?@TomSawyer如果数据已更改,您可以使用ReloadItemSatineXPath,但旋转不应影响基础数据,如果数据已存在,则不应要求重新加载数据。@OliverAtkinson我在旋转后更改了itemSize,但单元格中的imageview将不适合新的itemSize。这是屏幕截图:,因此,我必须向左/向右滑动以更新imageView,或者使用collectionView.reloadData()以使imageView适合新的单元格itemSize,如下所示。有没有更好的解决方法,我听说过constraint?与其保存大小并调用PerformBatchUpdate,您只需调用self.collectionView!。collectionViewLayout.invalidateLayout()然后在SizeFormiteIndeXPath中,只需从视图/collectionViews中获取新的边界看起来它应该可以在iOS11上工作,而不需要任何技巧
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
CGSize elementSize = CGSizeMake(screenWidth/screenDivide, 100);
return elementSize;
}