11

I have a UICollectionView which I have setup, everything works fine (selection, headers, etc), however, I want to change the scroll direction in some situations.

In short if I go into the story board and change the scrollDirection it works fine but I want to do it programatically!

I have tried to change the scroll direction of the collection view directly with something like

    [myCollectionView setScrollDirection:....and so on.......

But this does not work, I can not find scrollDirection or similar in there.

I have also tried to setup a flow layout but I am sure i am doing this wrong (i.e. trying to set a ViewLayout to a FlowLayout).

    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
    [myCollectionView setCollectionViewLayout:flowLayout];

This crashes with a lot of Constraint problems and I suspect I need to do a lot more work with the flowLayout (from what I have found it is a bit above me right now).

It should also be noted that I am using a custom cell, headers and footers.

In short is there an easy way to do this or not? OR does anyone know a good Flow Layout tutorial?

EDIT

I setup the collection view as such;

[myCollectionView setDataSource:self];
[myCollectionView setDelegate:self];

I implement these delegate methods and all work fine

viewForSupplementaryElementOfKind
numberOfSectionsInCollectionView
numberOfItemsInSection
cellForItemAtIndexPath
didSelectItemAtIndexPath

I have added the DataSource and Delegate to the .h and also the FlowLayout delegate BUT I am not sure what I should also have for the latter.

Most of the visual layout is done in Story Board, there are a few things such as Font, size and colour which I do programatically.

ANOTHER EDIT

This is the error when I try to change the FlowLayout, I also get this when I try and invalidate the layout.

Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)

"<NSAutoresizingMaskLayoutConstraint:0x89967f0 h=--& v=--& V:[menuCell:0x8991700(50)]>",
"<NSLayoutConstraint:0x8991200 menuCell:0x8991700.bottom == UILabel:0x8992be0.bottom + 100>",
"<NSLayoutConstraint:0x898fd50 UILabel:0x8992be0.top == menuCell:0x8991700.top + 3>"

Will attempt to recover by breaking constraint

Break on objc_exception_throw to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful.

Wayne Chen
  • 305
  • 2
  • 15
Recycled Steel
  • 2,272
  • 3
  • 30
  • 35
  • Does the view where the collection view is drawn conform to the UICollectionViewFlowLayoutDelegate Protocol? Are you sure the amount of content you are trying to draw is large enough to warrant the collection view to actually scroll? Can we see more of the setup of the collection view? You are headed in the right direction by trying to set the scroll direction on the Flow Layout, so good start! – Matthew Hallatt Jan 13 '14 at 16:44
  • @MatthewHallatt I have added a little more info. This is a big table, there could be 50-60 items in 4 or five sections. The collection view is a long bar at the bottom which scrolls horizontally, button can be clicked which make the collection expand to nearly most of the screen (which is working) but I want the scrolling to move to vertical scrolling. – Recycled Steel Jan 13 '14 at 17:04

4 Answers4

20

do this:

- (IBAction)changeDirection:(UIButton *)sender
{
     UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)[self.collectionView collectionViewLayout];
     if(layout.scrollDirection == UICollectionViewScrollDirectionHorizontal)
     {
        layout.scrollDirection = UICollectionViewScrollDirectionVertical;
     }
     else
     {
         layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
     }
}

It works for me.

Pratham Mehta
  • 293
  • 2
  • 13
5

In swift you can do this:

//From the collection view subclass
    if let layout: UICollectionViewFlowLayout = self.collectionViewLayout as? UICollectionViewFlowLayout {
        layout.scrollDirection = .Vertical
    }
prolfe
  • 1,354
  • 12
  • 16
0

Ok, try calling invalidateLayout on your collection view like so:

[myCollectionView.collectionViewLayout invalidateLayout];

This forces the collection view to update its layout at that point (See apple documentation here). I'm not certain, but I don't imagine this is called when you change the scroll direction.

See if that gets you anywhere near!

codercat
  • 22,873
  • 9
  • 61
  • 85
Matthew Hallatt
  • 1,310
  • 12
  • 24
  • I tried this but get the same result, I have for clarity put the entire error in my question too. I am fast getting to the point where I will simple add two collection views and show/hidden them when needed but it seems a waste of resources. – Recycled Steel Jan 14 '14 at 09:42
  • Are you setting up your own constraints in your cell? If so, programatically or in interface builder? The problem seems to be that you're maybe trying to keep the label height the same, but keep it a certain distance from both the top and the bottom of the cell. If you are setting your own constraints, try removing the one holding the label to the bottom of the cell, or maybe the one constraining the height of the label. Or maybe I've been barking up the wrong tree with this whole comment! – Matthew Hallatt Jan 14 '14 at 10:00
  • It does look like it is all done in interface builder. The are no constraints set in there so I assume they are done automatically. I tried to add some but the same. – Recycled Steel Jan 14 '14 at 10:13
  • Are you doing anything in the 'prepareForReuse' method on your cells? If not, try setting the text of the label to nil (@"") and any images to nil as well whilst you're at it, just in case! – Matthew Hallatt Jan 14 '14 at 10:20
  • I have tried return nil for the view in viewForSupplementaryElementOfKind which draws the headers and footers but that did the same. I amy make a copy and remove the whole header footer thing because (as you say) it is looking like something there. – Recycled Steel Jan 14 '14 at 10:27
  • and no not using prepareForReuse. – Recycled Steel Jan 14 '14 at 10:29
  • Are you using a custom subclass of UICollectionViewCell, or just the default? You say the cell is set up in interface builder: you should be able to turn off Autolayout in the first tab of the Utilities pane on the right hand side (See http://www.goodbyehelicopter.com/2012/02/arggh-xcode-4-3-auto-layout-is-on-by-default-how-to-turn-off-auto-layout/ for example). See if that helps. The errors caused are definitely down to Autolayout, so turning it off should fix those errors, but your cells may look wrong. – Matthew Hallatt Jan 14 '14 at 10:35
  • I will try without Autolayout. I am fast coming to the conclusion that Autolayout is useless your app changes orientation and contains lots of complicated components. – Recycled Steel Jan 14 '14 at 13:58
  • @MatthewHallett I have removed Autolayout which has stopped the crash, however, the collectionView does not change scroll direction. I am changing the flowLayout as before and invalidating the layout, is there anything else? – Recycled Steel Jan 14 '14 at 14:09
  • Got it to work (small error), this has also fixed with the Autolayout. – Recycled Steel Jan 14 '14 at 14:13
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/45212/discussion-between-matthew-hallatt-and-recycled-steel) – Matthew Hallatt Jan 14 '14 at 15:25
0

You can do it with property observer didSet{} with your collection view outlet.

Assuming that the outlet for the collectionView is myCollectionView, in the code add a didSet property observer to the outlet and change the layout's direction. Something like-

@IBOutlet weak var myCollectionView:UICollectionView!{
      didSet{
            let layout = contentCollectionView.collectionViewLayout as!
UICollectionViewFlowLayout
            layout.scrollDirection = .Vertical
        }
}

Normally a collectionView is dropped in storyboard from object library, it automatically comes with FlowLayout. You can change this layout's flow direction by telling your code that when I get my collection view, I want its layout's scroll direction to be horizontal or vertical.

Natasha
  • 6,651
  • 3
  • 36
  • 58