美文网首页00『 基础知识 』iOS bug修复ios
项目需求---scrollview嵌套导致滚动卡顿问题

项目需求---scrollview嵌套导致滚动卡顿问题

作者: Big丶Show | 来源:发表于2016-08-15 18:15 被阅读3989次

更新

<p>谢谢各位朋友帮我想主意。此项目需求解决方案总结如下:</p>

  1. tableview或者collection view通用办法,设置两个组。第一个组没有item或者cell,只有SectionHeader
    (这里如果是collectionview并且iOS9以下想要达到tableviewSectionHeaderView那样的悬停效果需要自定义布局。如果是iOS9以上可以通过一下两个属性设置
    @property (nonatomic) BOOL sectionHeadersPinToVisibleBounds NS_AVAILABLE_IOS(9_0);
    @property (nonatomic) BOOL sectionFootersPinToVisibleBounds NS_AVAILABLE_IOS(9_0);
    )

2.如果是tableview,还可以同时设置headerView以及sectionHeaderView,因为sectionHeaderView在tableview是plain的方式下是悬停的,而headerView是不悬停的。

3.本文章所写的最土的方法

</br>


<p>最近在做一个项目,首页是这样设计的</p>


首页.jpg

<p></p>

  • 问题背景
    <p>整体首页是一个scrollview。从上到下依次是banner,三个按钮,目录,collectionview</p>
    <p>希望滚动时,目录滚动导航栏下方时可以悬停,只有collectionview继续滚动</p>
  • 思考方式

<p>创建collectionview时设置scrollEnabled为No,在- (void)scrollViewDidScroll:(UIScrollView *)scrollView中根据contentOffset.y判断开启或关闭首页整体scrollviewcollectionviewscrollEnabled属性。</p>

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
            if (scrollView != _scrollview){//滚动的是 collectionview
                if (scrollView.contentOffset.y <=0) {
                    _scrollView.scrollEnabled = NO;
                }
            }else{//滚动的主scrollview
                CGFloat bottomOffset = _scrollview.contentSize.height - _scrollview.bounds.size.height ;
                if ((int)scrollView.contentOffset.y > (int)(bottomOffset) + 45) {
                    [scrollView setContentOffset:CGPointMake(0, bottomOffset + 49) animated:NO];
                   _collectionview.scrollEnabled = YES;
                }else {
                    [_collectionview setContentOffset:CGPointZero animated:NO];
                    _collectionview.scrollEnabled = NO;
                }
            }
        }
  • 问题
    <p>很快就引出来问题,因为两个scrollview嵌套,同一个手势不会同时控制两个scrollview。最明显的表现就是,手势拖动目录悬停在导航栏下面,但是collectionview无法继续滚动,也就是继续向下滚动无效。并且,如果通过collectionview向上滚动到顶部时scrollview无法继续滚动。也就是继续向上滚动无效。</p>
    <p>我思考着因为这是同一个拖拽手势,因此手势对象不变的话,或许应该改变手势所被添加的view上面,这样就改变了手势所操作的view
    因此,在- (void)scrollViewDidScroll:(UIScrollView *)scrollView判断中,将scrollEnabled的设置改成scrollview.panGestureRecognizer这一对象所操作的view的设置,于是尝试了以下代码</p>
    [scrollView removeGestureRecognizer:scrollView.panGestureRecognizer];
    [_collectionview addGestureRecognizer:scrollView.panGestureRecognizer];

<p>但是完全没有效果。之后也尝试了设置panGestureRecognizer.Enable属性,效果与scrollEnabled的设置是一样的,会出现卡顿。
google了一番,也没有找到合适的结局办法。只能动用一些土法子了。</p>
<p>因为赶项目并且能力有限,实在没办法深入研究。心里总想着更改panGestureRecognizer某些设置可以达到效果。如果有哪位大神已经做到,还请告知,小弟感激不尽。</p>


  • 解决方法
    <p>直接设置collectionview不可以滚动,根据请求到得数据动态设置collection view的高度,以及scrollviewcontentSize属性。
    但需求要求目录悬停,因此创建了两个目录,一个添加在scrollview的上面,一个添加在window上面。在- (void)scrollViewDidScroll:(UIScrollView *)scrollView判断,设置window上面的显示或隐藏。
    这样确实完美解决了同一个手势滑动两个scrollview卡顿的问题。
    </p>
  • 引出问题
    <p>
    这个问题也是我不喜欢把东西加载window上面的原因。因为上面的解决方式,多创建了一个目录在window上。大家如果用UIAlertController会有这种体验(UIAlertView不会),AlertController与我们自己加在window上得view在同一个window上面,并且系统默认的阴影效果盖不住我们创建的view,这样也就不会影响view在有弹框时的操作。
    已经结局了问题.png
    </p>
  • 解决方法
    <p>幸好controller的view是UIView,在view的基础上直接创建了一个目录添加view上面,使其覆盖scrollview。这样的思路,让我想起以前,在tableviewController上需要添加悬浮view也可以这样应用。
    你若问为啥不用UIAlertView就不存在这种问题了。臣妾做不到啊。</p>

<p>问题虽然也解决了,但方法还有待优化。还是那句话,如有大神已经找到更好的解决方法,还请告知,小弟感激不尽。</p>

相关文章

网友评论

  • Sevenuncle:昨天刚实现这个功能,哈哈哈,我用tableview,子collectionview,两者滚动互斥,KVO监视两者的contentOffset以及用消息通知的方式保证任何时候两者只有一个可以滚动,除有一点小顿挫,基本好用,再优化一下即可完美
  • narutog17:楼主,能写个demo么?
  • watermelon_lp:如果是mas布局,分为两个view,一个是下面的collectionView,另一个是上面的视图。监听collectionView的滚动,根据offsety同时改变上面视图的y值,控制y值的最大值和最小值,来达到效果。要是xib布局就直接改变约束就好了
  • 老司机Wicky:哥们,别的我不知道,你试那两句代码,第一句移除手势,你scrollview就没手势了,然后你collection添加scrollview的手势,这样添加的难道不是nil么
    Big丶Show:@老司机Wicky 突然发现是的。因为不是粘贴的全部代码,也不知道昨天实现起来的时候是不是就这样做的。如果是的话,改一下看来真的有可能做得到。
  • 72190bfd45c6:整体用tableview,目录栏为自定义的tableviewcell的header,滑动时候,有一个属性让目录停在上面,我找找之前的代码
    Big丶Show:@yf__fy 这个是可以 ,但是最上面的banner 和三个按钮也是要滑动的
  • 821ed344a41a:求demo~~这个问题我们技术部门研究了快2个星期也没突破,~~~
  • 等这姑娘老在我心里:为啥不用tableview呢
    Big丶Show:@我唔系启亮 哦,我明白你的意思了。 tableviewHeaderview 是不悬停的。但是tableview sectionHeaderView是可以悬停的。这样是可以做到上面的view滑动,下面的中间的view悬停。谢谢你的方法。
    f243b1d3c704:@Big丶Show 之前我也做过一个类似的,不过我的需求是,上方一个view,中间悬停的,然后下方就是一个tableView(三部分)然后我的做法是:把上方view 直接添加到tableView上,中间需要悬停的View作为tableView的组header,下面就是tableView的内容,上方View的显示需要更改tableView的contentInset才能显示出来,不过这样就引发了一个header会停在半空的状况,为了解决这个状况,我在scroll的时候更改tableView的contentInset的值,不过这也不能很好地解决,所以最后我也直接把悬停的View 直接添加到tableView上,再更改它的frame值................然后当我实现之后,发现tableView有一个属性,就是tableView.headerView(没记错的话),这个属性不同于组的headerView,可以很好地解决我之前的问题。所以打了这么多,这么乱......你可以试试这样的一个解决方法(直接看这里):View的主体可以用tableView,上方的banner和按钮可以作为一个View放到tableView.headerView上(注意这不是组的headerView),中间悬停的就作为组的headerView,下面内容就cell中嵌套一个collectionView.
    Big丶Show:@等这姑娘老在我心里 无论是用collection view 还是tableview,都会面临,banner,和三个button的view 继续上滑,而目录需要悬停。这样的需求,我想来只有通过scrollview嵌套tableview或者collection view了。这样就势必碰到这样的问题。
  • 不会骑名字:朋友,你这么做似乎会让collectionview不在复用了,数据量小的情况还好,数据量大了话……
    不会骑名字:@Big丶Show 是的,朋友,你可以造10000个假数据插入试一试
    Big丶Show:@真的不会起名字啊 这个还真没有想过。~请问,是cell的复用么?
  • Caiflower:为什么不把上面整体作为collectionView的header
    Big丶Show:@孤独的根号五 主要是collection view上面有三部分,只有其中一部分需要悬停的。
    孤独的根号五:@沫toghayn丶in 自己可以设置header的,而且可以悬停..
    沫toghayn丶in:@花菜ChrisCai collectionview没有header吧,自己添上去的也不会悬停

本文标题:项目需求---scrollview嵌套导致滚动卡顿问题

本文链接:https://www.haomeiwen.com/subject/vivusttx.html