[英]UICollectionView contentOffset changes when keyboard appears
我正在尝试在我的应用中实现PullDown To Search
功能。 为了实现这一点,我刚刚修改了位EGOTableViewPullRefresh ,除了一个问题之外它工作得很好。
问题
当用户打开应用程序后,将出现以下屏幕。 最初UICollectionView's
contentoffset
应为(0,0)
如果用户下拉集合视图,此时将出现以下屏幕, contentoffset
的UICollectionView
应为(0,-60)
用户可以通过在上面的屏幕中输入文本进行搜索。 如用户点击我的问题是在这个屏幕一旦出现UITextField
输入文本contentoffset
的UICollectionView
变化(0,-60)
到(0,-110)
和UI loosks像波纹管屏。 我不确定为什么会发生这种变化你能指导我解决这个问题吗?
有同样的问题。 覆盖viewWillAppear:
, viewDidLoad:
和文档中告诉的其他方法没有任何效果, TPKeyboardAvoidingScrollView
也没有帮助。 在收集视图超过2天后,我遇到了一个非常糟糕的解决方法。 想法是在键盘即将出现时锁定向上滚动,因此您的集合视图不会移动到任何地方,并在键盘结束动画后解锁滚动。 为此,您应该将UICollectionView
子类UICollectionView
以添加一个锁定滚动,订阅键盘通知并正确设置此标志的标志。
在实施此解决方法之前,我必须警告您,这是一个非常糟糕的主意,在执行此操作之前,您应该尝试其他所有操作。 不过,这有效......
所以这就是你做的:
在viewController的viewWillAppear中订阅键盘通知:
- (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 }
您稍后会处理通知
不要忘记取消订阅通知:
- (void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self]; // your custom code }
子类UICollectionView并添加标志:
@property (nonatomic, getter=isLocked) BOOL locked;
在集合视图中覆盖setContentOffset:
- (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]; }
在viewController中创建键盘处理方法以锁定和解锁滚动:
- (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]; }); }
警告! 这里有一个关于keyboardDidShow:
dispatch_after
的一点说明keyboardDidShow:
如果你在键盘显示后立即解锁滚动,将忽略锁定并且收集视图将向上滚动。 将其包装到dispatch_after
以在0.3秒后运行此代码并且运行良好。 这可能与运行循环有关, 应该在真实设备上测试,而不是在模拟器中测试。
我在UICollectionView中有一个UITableView并且得到了奇怪的滚动。 受@AnkH的启发我覆盖了我的UICollectionView并将其添加到构造函数中:
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)
在键盘可见时,也覆盖contentOffset并阻止contentOffset的所有修改。 完成。 问题是UITableView已经在其自身上触发了正确的contentOffset设置,但是父UICollectionView添加了自己的contentOffset,导致了灾难性的行为。 首先它滚动太远,然后太远了。 现在它完美无瑕!
处理这个也不是一个漂亮的解决方案
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
}
}
最简单的替代方法是使用UIViewController并添加自己的UICollectionView。 禁用键盘所有不良行为所需的疯狂黑客数量只是疯了。
问题解决! 通过UIViewController更改我的UICollectionViewController并使我的UICollectionView成为我的ViewController.view的子视图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.