繁体   English   中英

UICollectionView scrollToItemAtIndexPath在导航控制器中无法正常运行

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM