Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何定义旋转时CollectionView的大小_Ios_Objective C_Xcode_Uicollectionview - Fatal编程技术网

Ios 如何定义旋转时CollectionView的大小

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 {

我有一个带有2个CollectionView控制器的viewcontroller

我希望在旋转时,只有一个集合视图调整为自定义大小,而另一个视图保持不变

我尝试使用:

- (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;
}