Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView contentOffset changes when keyboard appears

I am trying to implement PullDown To Search feature in my app. To implement this i just modified bit EGOTableViewPullRefresh it is working good except an issue.

Issue

When user opens the application following screen shall appear. initially the UICollectionView's contentoffset shall be (0,0) enter image description here

If user pulls down the collection view the following screen shall appear at this point the contentoffset of UICollectionView shall be (0,-60) enter image description here

User can search by entering their text in the above screen. My issue is occurring in this screen as soon as user taps the UITextField to enter text contentoffset of UICollectionView changes (0,-60) to (0,-110) and UI loosks like bellow screen. I am not sure why this change occurs can you please guide me to resolve this?

enter image description here

like image 993
thavasidurai Avatar asked Jun 17 '14 06:06

thavasidurai


2 Answers

Had the same issue. Overriding viewWillAppear:, viewDidLoad: and other methods as told in documentation had no effect, TPKeyboardAvoidingScrollView didn't help either. After struggling with collection view for over 2 days I've come to a really bad workaround. The idea is to lock scrolling up when keyboard is about to appear, so your collection view will not move anywhere, and unlock scroll after keyboard ends animation. To do so you should subclass UICollectionView to add a flag that locks scroll, subscribe to keyboard notifications and set this flag properly.

Before you implement this workaround, I must warn you that this is a VERY bad idea, and you should try everything else before doing that. Still, this works...

So here is what you do:

  1. In viewWillAppear of your viewController subscribe for keyboard notifications:

    - (void)viewWillAppear:(BOOL)animated
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardDidShow:)
                                                     name:UIKeyboardDidShowNotification
                                                   object:nil];
        // you custom code here
    }
    

You will handle notifications later

  1. Don't forget to unsubscribe from notifications:

    - (void)viewWillDisappear:(BOOL)animated
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        // your custom code
    }
    
  2. Subclass UICollectionView and add flag:

    @property (nonatomic, getter=isLocked) BOOL locked;
    
  3. Override setContentOffset: in your collection view:

    - (void)setContentOffset:(CGPoint)contentOffset
    {
        if (contentOffset.y < self.contentOffset.y && self.isLocked) // user scrolls up
            contentOffset.y = self.contentOffset.y; // ignore new Y coordinate, so collection view will not scroll up
        [super setContentOffset:contentOffset];
    }
    
  4. In your viewController create methods for keyboard handling to lock and unlock scroll:

    - (void)keyboardWillShow:(NSNotification *)aNotification
    {
        [(LockableCollectionView *)self.collectionView setLocked:YES];
    }
    
    - (void)keyboardDidShow:(NSNotification *)aNotification
    {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [(LockableCollectionView *)self.collectionView setLocked:NO];
        });
    }
    

Warning! Here is a little clarification about dispatch_after in keyboardDidShow: If you unlock scroll right after keyboard did show, locking will be ignored and collection view will scroll up. Wrap it into dispatch_after to run this code after 0.3 seconds and it works well. This is probably related with run loops and should be tested on real devices, not in simulator.

like image 108
AnKh Avatar answered Oct 13 '22 23:10

AnKh


problem solve! changing my UICollectionViewController by a UIViewController and make my UICollectionView a subView of my ViewController.view.

like image 32
r0d0 Avatar answered Oct 13 '22 22:10

r0d0