UICollectionView contentOffset changes when keyboard appears

I am trying to implement the PullDown To Search function in my application. To implement this, I just changed the EGOTableViewPullRefresh bit ; it works well, except for the problem.

Question

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

If the user disables viewing the collection, the following screen should appear at this moment: contentoffset of UICollectionView should be (0,-60) enter image description here

The user can perform a search by entering their text on the screen above. My problem arises on this screen as soon as the user enters a UITextField to enter the text contentoffset from the UICollectionView changes (0,-60) to (0,-110) , and the user interface looks like the following screen. I'm not sure why this change is happening, can you direct me to solve this problem?

enter image description here

+6
source share
5 answers

There was the same problem. Overriding viewWillAppear: viewDidLoad: and the other methods described in the documentation did not affect, TPKeyboardAvoidingScrollView did not help either. After I struggled with viewing the collection for more than 2 days, I came up with a very bad workaround. The idea is to block scrolling when the keyboard is about to appear, so your collection view won't move anywhere and unlocks scrolling after animating the end of the keyboard. To do this, you must subclass UICollectionView to add a flag that blocks scrolling, subscribes to keyboard notifications, and sets this flag correctly.

Before you start using this workaround, I must warn you that this is a VERY bad idea, and before that you should try everything else. However, this works ...

So here is what you do:

  • In the WillAppear view of your viewController, sign up for a notification keyboard:

     - (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 process notifications later.

  1. Do not forget to unsubscribe from notifications:

     - (void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self]; // your custom code } 
  2. Subclass of 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 keyboard handling methods to lock and unlock scrolling:

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

A warning! Below is a little explanation about dispatch_after in keyboardDidShow: If you unlock the scroll immediately after the keyboard is displayed, the lock will be ignored and the collection will scroll up. Wrap it in dispatch_after to run this code after 0.3 seconds and it works well. This is probably due to run cycles and should be tested on real devices, not in the simulator.

+1
source

also not a great solution to handle this

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIKeyboardWillShowNotification, object: nil) 

 func keyboardWillShow() { let offset = self.collectionView!.contentOffset; self.collectionView!.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right:0 ) self.collectionView!.contentOffset = offset let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))) dispatch_after(delayTime, dispatch_get_main_queue()) { let offset = self.collectionView!.contentOffset; self.collectionView!.contentInset = UIEdgeInsets(top: 60, left: 0, bottom: 0, right:0 ) self.collectionView!.contentOffset = offset } } 
0
source

The simplest alternative is to use a UIViewController and add your own UICollectionView. The number of crazy hacks needed to disable all unwanted keyboard behavior is insane.

0
source

solve the problem of! change my UICollectionViewController using a UIViewController and make my UICollectionView a subspecies of my ViewController.view.

0
source

I had a UITableView inside a UICollectionView and got a weird scroll. Inspired by @AnkH, I override my UICollectionView and add it to the constructor:

 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidHide), name: NSNotification.Name.UIKeyboardDidHide, object: nil) 

Override contentOffset and block all modifications to contentOffset while the keyboard is visible. Done. The problem is that the UITableView already starts the proper setting of the contentOffset by itself, but then the parent UICollectionView adds its own contentOffset, resulting in catastrophic behavior. At first he scrolled too far, then too far down. Now it works flawlessly!

0
source

Source: https://habr.com/ru/post/970921/


All Articles