如何在枚举UIScrollView的子视图时排除滚动指示器?

时间:2012-06-10 01:20:56

标签: iphone ios ipad uiscrollview uikit

我正在尝试调整subviews子类中的UIScrollView,但我不想打扰滚动指示器。似乎没有任何公共接口可以访问这些并且我想检查视图是否是滚动指示符之一(以便我可以忽略它)。

UIScrollView.h声明这两个iVars:

UIImageView* _verticalScrollIndicator;
UIImageView* _horizontalScrollIndicator;

...但我尝试了以下操作并收到了链接器错误:

for(UIView* v in self.subviews)
{
    // Ignore the scroll-indicator views
    if( (v == _horizontalScrollIndicator) ||
        (v == _verticalScrollIndicator))
    {
        continue;
    }
    // View is one of mine - do stuff to it...
}
Apple显然不希望你搞砸这些,在这种情况下,他们应该做一些聪明的事情,以便从subviews返回的数组不包括它们(来到Apple,它并不那么难!),但在那之前我怎么能忽略它们?

6 个答案:

答案 0 :(得分:5)

最终成为我的解决方案

BOOL showsVerticalScrollIndicator = self.showsVerticalScrollIndicator;
BOOL showsHorizontalScrollIndicator = self.showsHorizontalScrollIndicator;

self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;

// loop through self.subviews here

self.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
self.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;

答案 1 :(得分:2)

据推测,您可以控制UIScrollView中的观点。为什么不维护自己的那些视图?这样,您就可以安全地防止UIScrollView实现的任何未来变化。

答案 2 :(得分:1)

我遇到了同样的问题,我开始考虑查看这两个UIImageView的值,以确定它们是否存在。他们确实有一个非常独特的签名:

<UIImageView: 0x8ab3e00; frame = (313 812.5; 7 3.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x8ab9740>>
<UIImageView: 0x8ab3e90; frame = (314.5 522; 3.5 341); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x8ab3f20>>

你可以听的其他钩子。在这一点上,选择方式并不理想,但并不多...

这是一个例子。在这种情况下,我循环浏览scrollview的子视图,根据子视图确定滚动视图的最佳contentSize高度,当它开始出现时带有一些时髦的值,这让我觉得它是滚动条和我打电话......

CGRect contentRect = CGRectZero;
for (UIView *view in self.myScrollView.subviews) {
    //exclude scroll bars, the width/height is 3.5 for non-retina or 7 
    //for retina. you can put some logic in here if you like to check
    //the appropriate 3.5/7.0 values for the respective screen densities
    if(view.frame.size.width > 7.0f && view.frame.size.height > 7.0f) {
        contentRect = CGRectUnion(contentRect, view.frame);
    }
}
container.contentSize = CGSizeMake(container.contentSize.width, contentRect.size.height);

如果检查每个UIView的框架对你来说不够具体,你也可以确保它是一个UIImageView。

我认为这是目前唯一的“真正”解决方案。我个人而不是必须维持另一组观点。

修改

这是我使用的合并方法:

-(bool)isProbablyAScrollBar:(UIView*)view {
    CGFloat screenScale = [[UIScreen mainScreen] scale];
    return (([view isKindOfClass:[UIImageView class]]) && (view.frame.size.width <= (screenScale*3.5f) || view.frame.size.height <= (screenScale*3.5f)));
}

答案 3 :(得分:0)

滚动指示器视图是在滚动视图的整个生命周期中添加和删除的,还是只添加一次并隐藏并显示为必要?如果是后者,你可以在init中存储你自己的引用...而不是使用私有的ivars,并按照你已经尝试过的方式继续。

答案 4 :(得分:0)

我的解决方案是:

UIView* MYContentView=[[UIView alloc] initWithRect: CGrectMake:(0,0,Scrollview.frame.size.width, scrollview.frame.size.height)];

[ScrollView addsubview: MYContentView];

然后我将所有图像添加到MYContentView,稍后重新调整了MYContentView和

  [ScrollView setContentSize:Cgsize];

现在,您可以枚举MYContentView中的所有图像,而无需担心滚动条。

这样做的:

while ([[MYContentView subviews] count]>0) {
    [[[MYContentView subviews]lastObject] removeFromSuperview];
}

仅删除了图片。希望这有帮助

答案 5 :(得分:0)

基于MrTristan的方法。我认为他错误地乘以屏幕尺度。

+ (NSArray <UIView *> *)reservedSubviewsInUIScrollView:(UIScrollView *)view
{
    BOOL (^isProbablyAScrollBar)(UIView *s) = ^BOOL(UIView *s) {
        return [s isKindOfClass:[UIImageView class]] && (s.frame.size.width <= 3.5 || s.frame.size.height <= 3.5);
    };

    NSMutableArray <UIView *> *reserved = [NSMutableArray new];
    for(UIView *s in view.subviews)
    {
        if(isProbablyAScrollBar(s))
        {
            [reserved addObject:s];
        }
    }
    return reserved;
}