【问题标题】:UICollectionView contentOffset changes when keyboard appearsUICollectionView contentOffset 在键盘出现时发生变化
【发布时间】:2014-08-07 01:10:43
【问题描述】:

我正在尝试在我的应用中实现PullDown To Search 功能。为了实现这一点,我只是修改了位 EGOTableViewPullRefresh ,除了一个问题之外它运行良好。

问题

当用户打开应用程序时,将出现以下屏幕。最初 UICollectionView's contentoffset 应为 (0,0)

如果用户下拉集合视图,此时将出现以下屏幕,UICollectionViewcontentoffset 应为 (0,-60)

用户可以通过在上面的屏幕中输入他们的文字进行搜索。一旦用户点击UITextField 输入文本UICollectionViewcontentoffset(0,-60) 更改为(0,-110),我的问题就会出现在此屏幕上,并且UI 看起来像波纹管屏幕。我不确定为什么会发生这种变化,请您指导我解决这个问题吗?

【问题讨论】:

  • 向我们展示视图层次结构?你用过 cocoacontrols.com 的 TPKeyboardAvoidingScrollView 类吗?
  • 所以没有漂亮而简单的决定来处理这个问题?

标签: ios objective-c uiscrollview uicollectionview contentoffset


【解决方案1】:

有同样的问题。覆盖viewWillAppear:viewDidLoad: 和文档中所述的其他方法无效,TPKeyboardAvoidingScrollView 也无济于事。在与收藏视图苦苦挣扎 2 多天后,我遇到了一个非常糟糕的解决方法。这个想法是在键盘即将出现时锁定向上滚动,因此您的收藏视图不会移动到任何地方,并在键盘结束动画后解锁滚动。为此,您应该继承 UICollectionView 以添加锁定滚动的标志、订阅键盘通知并正确设置此标志。

在您实施此解决方法之前,我必须警告您这是一个非常糟糕的主意,您应该在这样做之前尝试其他所有方法。不过,这行得通...

这就是你要做的:

  1. 在 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
    }
    

您稍后会处理通知

  1. 别忘了取消订阅通知:

    - (void)viewWillDisappear:(BOOL)animated
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        // your custom code
    }
    
  2. 子类 UICollectionView 并添加标志:

    @property (nonatomic, getter=isLocked) BOOL locked;
    
  3. 覆盖 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];
    }
    
  4. 在您的 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];
        });
    }
    

警告!这里有一点关于dispatch_after in keyboardDidShow: 的说明 如果您在键盘显示后立即解锁滚动,则锁定将被忽略并且集合视图将向上滚动。将其包装成 dispatch_after 以在 0.3 秒后运行此代码,它运行良好。这可能与运行循环有关,应该在真实设备上进行测试,而不是在模拟器中。

【讨论】:

  • 当键盘已经在屏幕上时,如果你再次点击 UITextfield,它就不起作用了。
  • 我认为不覆盖 - (void)setContentOffset:(CGPoint)contentOffset 并覆盖另一个方法可能更正确: -(void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition 动画:(BOOL)动画
  • FWIW - 我发现如果您按原样使用 Apple 示例中的键盘避免代码,则会发生此行为。我不得不修改它以考虑到键盘出现时表格视图的偏移量。
【解决方案2】:

也不是处理这个问题的好方法

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
    }
}

【讨论】:

    【解决方案3】:

    最简单的替代方法是使用 UIViewController 并添加您自己的 UICollectionView。禁用键盘所有不良行为所需的疯狂黑客数量简直是疯狂的。

    【讨论】:

    • 它对我不起作用...我在使用 UIViewController 和 UICollectionView 时遇到了这个问题。
    【解决方案4】:

    问题解决!通过 UIViewController 更改我的 UICollectionViewController 并使我的 UICollectionView 成为我的 ViewController.view 的子视图。

    【讨论】:

    • 出于某种原因,UICollectionViewController 在层次结构中添加了一个滚动视图作为顶视图。那是键盘出现时修改的视图。
    • 它对我不起作用...我在使用 UIViewController 和 UICollectionView 时遇到了这个问题。
    【解决方案5】:

    我在 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,导致了灾难性的行为。首先它向上滚动太远,然后向下滚动太远。现在它可以完美运行了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-19
      • 2012-06-20
      • 2018-09-18
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多