[英]UICollectionView scrollToItemAtIndexPath not functioning properly in navigation controller
我有一个方法,我用它滚动到我的collectionView的底部
- (void) scrollToBottom {
if (_messagesArray.count > 0) {
static NSInteger section = 0;
NSInteger item = [self collectionView:_myCollectionView numberOfItemsInSection:section] - 1;
if (item < 0) item = 0;
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForItem:item inSection:section];
[_myCollectionView scrollToItemAtIndexPath:lastIndexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:YES];
}
}
而且效果很好! 我从来没有遇到任何问题,它的工作方式是100%一致的。 。 。 用模态视图演示。 但是,如果我将viewController推送到导航控制器上,它就不起作用了。 相反,只有超过15个单元格才有效。 一旦我达到至少15个细胞,它再次开始表现完美。 在15个单元格之前,它要么根本不滚动,要么滚动一点。
我意识到这是一个很长的镜头,但我在这个问题上摸不着头脑,我想也许有人可能知道发生了什么事。
故障排除:
你有登录以确保它正在运行吗? 是
您是否已记录索引路径以确保其尝试滚动到正确的索引路径? 是
UIViewController
有一个automaticallyAdjustsScrollViewInsets
属性,并且在UINavigationController
继承了该属性。 在self.navigationController
它设置为NO
,它将不会调整您的插入,如此处所述
我发现了这个问题。
由于某种原因,NavigationController自动调整我的顶级内容插入。 我能够通过添加以下内容来阻止此行为:
- (void) scrollToBottom {
if (_isNavigationControllerVersion) {
_myCollectionView.contentInset = UIEdgeInsetsZero;
}
if (_messagesArray.count > 0) {
static NSInteger section = 0;
NSInteger item = [self collectionView:_myCollectionView numberOfItemsInSection:section] - 1;
if (item < 0) item = 0;
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForItem:item inSection:section];
[_myCollectionView scrollToItemAtIndexPath:lastIndexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:YES];
}
}
因此,由于你的.gif文件表明当键盘打开时问题正在发生,我只能假设底部滚动位于集合视图的内容插入内,即使它位于键盘后面。
当键盘出现/消失时,请确保重置内容插入。 我将在一些示例代码中编辑。
首先,您需要注册通知:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
这应该在viewDidLoad
。 不要忘记在dealloc
removeObserver
。
现在在这些方法中设置内容insets:
- (void)keyboardWasShown:(NSNotification *)aNotification {
CGSize kbSize = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets insets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
yourCollectionView.contentInset = Insets;
yourCollectionView.scrollIndicatorInsets = Insets;
}
- (void) keyboardWillHide:(NSNotification *)aNotification {
UIEdgeInsets insets = UIEdgeInsetsZero;
yourCollectionView.contentInset = contentInsets;
yourCollectionView.scrollIndicatorInsets = contentInsets;
}
在我可以访问单元格的上下文中遇到同样的问题,我能够使用scrollRectToVisible
,它似乎没有表现出这种行为。
我找到了很好的解决方案在这里
- (void)scrollToBottomAnimated:(BOOL)animated
{
if ([self.collectionView numberOfSections] == 0) {
return;
}
NSInteger items = [self.collectionView numberOfItemsInSection:0];
if (items == 0) {
return;
}
CGFloat collectionViewContentHeight = [self.collectionView.collectionViewLayout collectionViewContentSize].height;
BOOL isContentTooSmall = (collectionViewContentHeight < CGRectGetHeight(self.collectionView.bounds));
if (isContentTooSmall) {
// workaround for the first few messages not scrolling
// when the collection view content size is too small, `scrollToItemAtIndexPath:` doesn't work properly
// this seems to be a UIKit bug, see #256 on GitHub
[self.collectionView scrollRectToVisible:CGRectMake(0.0, collectionViewContentHeight - 1.0f, 1.0f, 1.0f)
animated:animated];
return;
}
// workaround for really long messages not scrolling
// if last message is too long, use scroll position bottom for better appearance, else use top
// possibly a UIKit bug, see #480 on GitHub
NSUInteger finalRow = MAX(0, [self.collectionView numberOfItemsInSection:0] - 1);
NSIndexPath *finalIndexPath = [NSIndexPath indexPathForItem:finalRow inSection:0];
CGSize finalCellSize = [self.collectionView.collectionViewLayout sizeForItemAtIndexPath:finalIndexPath];
CGFloat maxHeightForVisibleMessage = CGRectGetHeight(self.collectionView.bounds) - self.collectionView.contentInset.top - CGRectGetHeight(self.inputToolbar.bounds);
UICollectionViewScrollPosition scrollPosition = (finalCellSize.height > maxHeightForVisibleMessage) ? UICollectionViewScrollPositionBottom : UICollectionViewScrollPositionTop;
[self.collectionView scrollToItemAtIndexPath:finalIndexPath
atScrollPosition:scrollPosition
animated:animated];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.