转载请保留地址wossoneri.com

问题

首先看一下我之前写的demo:link

demo是封装了一个控件,直接在MainViewControllerviewWillAppear里初始化,并且调用一个初始化滚动到中间的方法,方法主要是调用了

- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;

方法,在初始化后将其滚动到中间的区域。不过,当我在项目里使用的时候,遇到了调用该方法却无法滚动到中间的情况。

我的使用步骤是:在我界面的UIView中,创建该控件对象并且调用滚动到中间的方法。

scrollToItemAtIndexPath使用

发现效果无法实现,我第一时间检查了函数有没有调用,然后发现是调用的了,但没有出现该出现的效果。所以简单看一下该方法的官方注释。xcode提示的描述是:

Scrolls the collection view contents until the specified item is visible.只是方法的作用,并没有说使用条件。为了快速解决问题,google了一下scrolltoitematindexpath not working,在这里:link找到了答案:

不知道这是一个bug还是一个特性,每当在UICollectionView显示它的subview之前调用scrollToItemAtIndexPath:atScrollPosition:Animated方法,UIKit就会报错。

所以要解决它,就应该在viewController中,在你能确认CollectionView完全计算出其subview布局的地方去调用这个方法。比如在viewDidLayoutSubviews里调用就没有问题。

方法的意思已经明确,就是找到一个能计算出collectionview的所有布局地方调用滚动方法。但我的界面使用的是自动布局,只在模块外有一个viewController,其余的都是在UIView中创建添加,所以在我使用这个控件对象的地方,我无法复写viewController的方法。所以想了几个办法。

-layoutsubviews

既然情况发生在UIView中,那首先想到的是重写该方法。重写之前,看一下文档说明:

Lays out subviews.

Discussion

The default implementation of this method does nothing on iOS 5.1 and earlier. Otherwise, the default implementation uses any constraints you have set to determine the size and position of any subviews.

Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.

You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.

该方法为子view布局。

子类可以复写该方法为子view实现更精确的布局。但你只应该在用自动布局时无法实现效果时用它。而且你不应该直接调用该方法,如果需要强制刷新布局,调用setNeedLayout,会在下一次绘制刷新前更新布局。调用layoutIfNeed可以立即刷新布局。

看起来这个方法有用,我便试了一下。

[self setNeedLayout];
[self layoutIfNeed];
[myPicker scrollToCenter];

然而还是没有效果。

view.window

前面的方法没效果,我又想了一下scrolltoitematindexpath的实现条件,是在UICollectionView显示之后调用才有效,所以我需要在UIView中获得它显示的状态再去滚动。幸好,我的控件也是继承UIView的,其中有这么一个属性:

Property: window

This property is nil if the view has not yet been added to a window.

也就是说这个属性值代表着这个view有没有放在窗口中显示,那么我就需要在当前UIView的生命周期中检查myPicker对象的这个属性就好了。所以最后的解决方法是,起一个子线程,对myPicker的状态进行检查,当状态为显示的时候调用滚动方法:

NSThread *checkShownThread;
checkShownThread = [[NSThread alloc] initWithTarget:self selector:@selector(checkIfViewIsShowing) object:nil];
[checkShownThread start]; - (void)checkIfViewIsShowing {
while (1) {
if (hPicker.window != nil) {
break;
}
} dispatch_async(dispatch_get_main_queue(), ^{
[hPicker scrollToCenter];
}); [checkShownThread cancel];
checkShownThread = nil;
}

小结

这个bug只是一个很小的bug,我记录它的原因,一方面是解决过程中学习到了一些不了解的方法,另一方面是记录一下解决问题的思路,希望可以对以后的学习有帮助。也希望将来回头看这一段的时候可以对问题有更好的解决思路。

[iOS] UICollectionView初始化滚动到中间的bug的更多相关文章

  1. iOS UICollectionView 在滚动时停在某个item位置上

    方法一:实现UIScrollView的代理,然后实现下面这个方法 #pragma mark - UIScrollViewDelegate//预计出大概位置,经过精确定位获得准备位置- (void)sc ...

  2. [iOS] UICollectionView实现图片水平滚动

    最新更新: 简单封装了一下代码,参考新文章:UICollectionView实现图片水平滚动 先简单看一下效果: 新博客:http://wossoneri.github.io 准备数据 首先先加入一些 ...

  3. iOS无限循环滚动scrollview

    经常有园友会问"博主,有没有图片无限滚动的Demo呀?", 正儿八经的图片滚动的Demo我这儿还真没有,今天呢就封装一个可以在项目中直接使用的图片轮播.没看过其他iOS图片无限轮播 ...

  4. iOS关于菜单滚动视图实现

    菜单滚动视图也是在项目开发过程中比较常用到的功能,先直接看效果图 实现的效果如下: 当菜单个数的总长度超过一个屏宽度就计算每一个的文字宽度,若没有则只进行一个屏平分,点击菜单项时,滚动的视图位置会随着 ...

  5. Android RecyclerView 滚动到中间位置

    最近看到QQ音乐的歌词每次滑动后都可以滚回到中间位置.觉得甚是神奇,打开开发者模式显示布局,发现歌词部分不是采用 android 控件的写的,应该是前端写的.于是,我想,能不能用 recyclerVi ...

  6. UITableViewCell上放UICollectionView ,UICollectionViewCell无法复用bug

    如题: UITableViewCell上放UICollectionView ,UICollectionViewCell无法复用bug 如果UITableViewCell的size大于整个collect ...

  7. 处理ios的overflow滚动bug

    先说说这个bug的场景 .container{ height:100vh; overflow-y:scroll; } 没毛病,总有这种类似的情况,需要在容器内滚动,但是!这种容器内的滚动在ios上面处 ...

  8. iOS UICollectionView之二(垂直滚动)

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

  9. iOS UICollectionView之-(水平滚动)

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

随机推荐

  1. 剑指offer五之用两个栈实现队列

    一.题目 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 二.思路 1.Push操作:将数据直接压入stack1即可 2.Pop操作:将stack1中的数据全部弹 ...

  2. Deep Learning (中文版&英文版)

    Bengio Yoshua,Ian J. Goodfellow 和 Aaron Courville共同撰写的<深度学习>(Deep Learning)是一本为了帮助学生及从业者入门机器学习 ...

  3. (转) argparse — 解析命令参数和选项

    原文地址:https://pythoncaff.com/docs/pymotw/argparse-command-line-option-and-argument-parsing/166 https: ...

  4. 全网最详细的Windows里下载与安装Sublime Text *(图文详解)

    不多说,直接上干货! 前言 这是代码编程软件,可以性感编程自己代码,有着非常丰富的插件,界面整洁清爽.第一次使用可能不习惯,当你使用一段时间之后,你就会爱上它. 下载与安装 1.下载:目前官方的正式版 ...

  5. [Java初探实例篇02]__流程控制语句知识相关的实例练习

    本例就流程控制语句的应用方面,通过三个练习题来深入学习和巩固下学习的流程控制语句方面的知识,设计到,if条件判断语句,switch多分支语句,for循环语句及其嵌套多层使用,while循环语句. 练习 ...

  6. 探讨e.target与e.currentTarget

    target与currentTarget两者既有区别,也有联系,那么我们就来探讨下他们的区别吧,一个通俗易懂的例子解释一下两者的区别: <!DOCTYPE html> <html&g ...

  7. java web 机试

    经过近一个月的学习,我们的java web已经学习完了. 这是我们这次的机试题. 一:题目 请利用MVC设计模式,并使用JSP.Servlet.JSTL和JQuery等技术实现动态条件的分页显示查询. ...

  8. SSL编程(2).NET最简单的客户端

      在Windows平台上,实现SSL的.NET类是System.Net.Security.SslStream类.这个类既可以用于建立SSL服务,也可以用来作为SSL客户端连接远端的SSL服务. 最简 ...

  9. 在Java的反射中,Class.forName和ClassLoader的区别

    前言 最近在面试过程中有被问到,在Java反射中Class.forName()加载类和使用ClassLoader加载类的区别.当时没有想出来后来自己研究了一下就写下来记录一下. 解释 在java中Cl ...

  10. Mac 自带的Apache php 狼神的

    开启服务:sudo /usr/sbin/apachectl start 停止服务:sudo /usr/sbin/apachectl stop 重启服务:sudo /usr/sbin/apachectl ...