Ios UICollectionViewFlowLayout未使方向更改时的权限无效

Ios UICollectionViewFlowLayout未使方向更改时的权限无效,ios,uicollectionview,uicollectionviewlayout,Ios,Uicollectionview,Uicollectionviewlayout,我有一个带有UICollectionViewFlowLayout的UICollectionView。我还实现了UICollectionViewDelegateFlowLayout协议 在我的数据源中,我有一堆UIViewController,它们响应一个定制协议,所以我可以询问它们的大小和其他一些东西 在FlowLayout委托中,当它请求sizeForItemAtIndexPath:,我返回从协议中获得的项目大小。实现我的协议的ViewController根据方向返回不同的项目大小 现在,如果

我有一个带有UICollectionViewFlowLayout的UICollectionView。我还实现了UICollectionViewDelegateFlowLayout协议

在我的数据源中,我有一堆UIViewController,它们响应一个定制协议,所以我可以询问它们的大小和其他一些东西

在FlowLayout委托中,当它请求sizeForItemAtIndexPath:,我返回从协议中获得的项目大小。实现我的协议的ViewController根据方向返回不同的项目大小

现在,如果我将设备方向从纵向更改为横向,则没有问题(横向中的项目较大),但如果我将其更改回来,则会收到以下警告:

    the item width must be less that the width of the UICollectionView minus the section insets left and right values.
    Please check the values return by the delegate.
它仍然有效,但我不喜欢收到警告,所以也许你可以告诉我我做错了什么。还有一个问题。如果我没有在WillAnimateRotationInterfaceOrientation中告诉我的collectionViews collectionViewLayout无效,则永远不会调用sizeForItemAtIndexPath:


希望你明白我的意思。如果您需要其他信息,请告诉我:)

一种解决方案是使用KVO并侦听对集合视图的superview框架的更改。调用-reloadData将起作用并消除警告。这里有一个潜在的时间问题

// -loadView
[self.view addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];

// -dealloc
[self.view removeObserver:self forKeyPath:@"frame"];

// KVO Method
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    [collectionView_ reloadData];
}

这个答案迟了,但被接受的答案对我不起作用。我同情OP想要一个火,忘记UICollectionViewFlowLayout。我建议在视图控制器中使布局无效实际上是最好的解决方案

我想要一条水平滚动的单元格线,以视图为中心,包括纵向和横向

我将UICollectionViewFlowLayout子类化

我重写prepareLayout以重新计算插图,然后调用[super prepareLayout]

我重写了collectionViewContentSize的getter,以确保内容大小正确

布局本身并没有失效,即使边界随着重新定向而改变

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // does the superclass do anything at this point?
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    // do whatever else you need before rotating toInterfaceOrientation

    // tell the layout to recalculate
    [self.collectionViewLayout invalidateLayout];
}

UICollectionViewFlowLayout在方向之间保持滚动位置。同一单元格只有在为正方形时才会居中

我不知道它是否对某人有帮助,但最后的答案没有一个对我有帮助,因为我正在使用一些
UIViews
UIScrollView


我将根据一些事件以编程方式打开UIView。所以我不能使用
-(void)willRotateToInterfaceOrientation:
invalidateLayout
重新加载数据
,因为:
1.invalidateLayout”在下一个视图布局更新周期中发生。
2.“为了提高效率,集合视图仅显示可见的单元格和补充视图。”

对我有效的是在中使用collectionView父视图(UIView)的宽度:



出于某种原因,collectionView框架在调用此函数时具有纵向宽度。。。使用
int currentWidth=self.frame.width
帮助我解决这个问题。

我在这里使用了两个答案的组合,我们都试图做的是让集合视图看起来像一个表视图,但不使用UITableView并在单个列中获取项(最有可能)

-(void)视图将转换大小:(CGSize)带有转换协调器的大小:(id)协调器{
[super ViewWillTransitionSize:size with TransitionCoordinator:coordinator];
[self.collectionView.collectionViewLayout invalidateLayout];
}

@0mahc0的答案对我有效,但只是部分有效

我没有旋转问题,因为我强制我的应用程序只能处于纵向模式,但我的解决方案可以帮助其他人解决同样的问题

每次视图出现时都会显示警告。警告的原因非常清楚,我们已经在UICollectionView的左侧和右侧定义了部分插入。检查interface builder,您将在度量中看到这些定义的值

@0mahc0的解决方案是可行的,但我想将单元格拉伸到最大宽度,所以我删除了部分的插图,否则我将在左右两侧都有一个“边距”

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsZero;
}

您可以转到interface builder并将左右插入的值更改为零,而不是实现委托方法。

iOS8:我可以使警告静音的唯一方法是在旋转到较大尺寸时的转换过程中调用invalidate,在旋转到较小尺寸时的转换之前调用invalidate

    self.sizeForCollectionView = size; //used to determine collectionview size in sizeForItem
    if (size.width <= size.height) {
        [self.collectionView.collectionViewLayout invalidateLayout];
    }

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        if (size.width > size.height) {
            [self.collectionView.collectionViewLayout invalidateLayout];
        }
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    }];
self.sizeForCollectionView=size//用于确定以sizeForItem为单位的collectionview大小
if(尺寸、宽度、尺寸、高度){
[self.collectionView.collectionViewLayout invalidateLayout];
}
}完成:^(id上下文){
}];

是@meelawsh答案的变体,但在Swift中,没有
self.sizeForCollectionView
属性:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    guard let collectionView = self.collectionView else {
        return
    }

    if size.width > collectionView.frame.width {
        // bigger

        let animation: (UIViewControllerTransitionCoordinatorContext)->(Void) = {
            context in
            collectionView.collectionViewLayout.invalidateLayout()
        }

        coordinator.animateAlongsideTransition(animation, completion: nil)
    } else {
        // smaller
        collectionView.collectionViewLayout.invalidateLayout()
    }
}

我也有同样的问题,你知道出了什么问题吗?还没有,但我仍在研究解决方案。如果我找到一个,我会让你知道这可能有效,但是UIView框架不是符合KVO的,根据文档,Bob Wakefield的答案与任何黑客无关。@cynistersix有更现代的答案。正在弃用旋转接口。我确实认为使布局无效比重新加载数据要好。我建议你使布局无效,而不是重新加载数据。你必须拥有超级能力@BobWakefield。。。我已经做了这个改变:)更新了答案我实际上感觉不到做
协调器的区别。动画长边过渡(动画,完成:无)
。因此,我认为只有
collectionView.collectionViewLayout.invalidateLayout()
就足够了。如果不让协调器在转换过程中设置动画,只调用invalidateLayout对我来说是行不通的。这似乎是itIn interface builder的插入值为零,但我仍然收到此错误。
    self.sizeForCollectionView = size; //used to determine collectionview size in sizeForItem
    if (size.width <= size.height) {
        [self.collectionView.collectionViewLayout invalidateLayout];
    }

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        if (size.width > size.height) {
            [self.collectionView.collectionViewLayout invalidateLayout];
        }
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    }];
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    guard let collectionView = self.collectionView else {
        return
    }

    if size.width > collectionView.frame.width {
        // bigger

        let animation: (UIViewControllerTransitionCoordinatorContext)->(Void) = {
            context in
            collectionView.collectionViewLayout.invalidateLayout()
        }

        coordinator.animateAlongsideTransition(animation, completion: nil)
    } else {
        // smaller
        collectionView.collectionViewLayout.invalidateLayout()
    }
}