Rafał Sroka
Rafał Sroka

Reputation: 40028

Disable focus triggered scrolling of UICollectionView

Is there a way to disable automatic scrolling of the UICollectionView when cell gets focused? I want to adjust the content offset of the cell manually when it gets into focus.

I wan't to update the content offset in:

- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context
       withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
    [coordinator addCoordinatedAnimations:^
     {
         [UIView animateWithDuration:[UIView inheritedAnimationDuration]
                          animations:^
          {
              // Move next focused cell.
              if ([context.nextFocusedView isKindOfClass:[YBZEventCollectionViewCell class]])
              {
                  UICollectionViewCell *cell = (UICollectionViewCell *)context.nextFocusedView;

                  CGPoint offset = CGPointMake(CGRectGetMinX(cell.frame), 0.0f);

                  [_collectionView setContentOffset:offset];
              }
          }];

     } completion:nil];
}

This works but since the focus engine also moves my cell (scrolls it) I end up with animation which is not smooth, there is a "kick" at the end of it.

Upvotes: 7

Views: 4115

Answers (3)

David Haynes
David Haynes

Reputation: 933

Just ran into this exact thing. To disable automatic scrolling of a UICollectionView when focus changes, just disable scrolling in the 'Scroll View' properties for the collection view in interface builder:

enter image description here

Upvotes: 3

Justin Voss
Justin Voss

Reputation: 6384

Since UICollectionView subclasses UIScrollView, your collection view delegate can implement scroll view delegate methods. The one you probably want is:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                 withVelocity:(CGPoint)velocity
          targetContentOffset:(inout CGPoint *)targetContentOffset

The targetContentOffset will be the scroll offset that UIKit will scroll to by default, but if you change the value then UIKit will scroll there instead.

If you really truly don't want UIKit to do any automatic scrolling for your whatsoever, you can always just disable scrolling entirely by setting scrollEnabled to NO.

Upvotes: -1

Jeroen Bakker
Jeroen Bakker

Reputation: 2169

I don't know what you mean with 'automatic scrolling', but to alter a collection view cell you could use the didUpdateFocusInContext in your custom cell class.

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    coordinator.addCoordinatedAnimations({ [unowned self] in
        if self.focused {
            self.titleTopConstraint.constant = 27

            self.titleLabel.textColor = UIColor.whiteColor()
        } else {
            self.titleTopConstraint.constant = 5

            self.titleLabel.textColor = UIColor(red: 100 / 255, green: 100 / 255, blue: 100 / 255, alpha: 1)
        }
        self.layoutIfNeeded()
    }, completion: nil)
}

Or if you don't have a custom cell, use the didUpdateFocusInContext from the UICollectionViewDelegate.

func collectionView(collectionView: UICollectionView, didUpdateFocusInContext context: UICollectionViewFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    coordinator.addCoordinatedAnimations({ () -> Void in
        if let indexPath = context.nextFocusedIndexPath, let cell = collectionView.cellForItemAtIndexPath(indexPath) {
            // the cell that is going to be focused
        }
        if let indexPath = context.previouslyFocusedIndexPath, let cell = collectionView.cellForItemAtIndexPath(indexPath) {
            // the cell that is going to be unfocused
        }
    }, completion: nil)
}

Upvotes: -1

Related Questions