Reputation: 19281
I'm trying to adjust my subviews
in a UIScrollView
subclass, but I don't want to disturb the scroll indicators. There doesn't seem to be any public interface to access these and I want to check if a view is one of the scroll indicators or not (so that I can ignore it).
UIScrollView.h
declares these two iVars:
UIImageView* _verticalScrollIndicator;
UIImageView* _horizontalScrollIndicator;
...but I tried the following and got a linker error:
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 obviously don't want you messing with these, in which case they should do something clever so that the array returned from subviews
doesn't include them (come on Apple, it's not that hard!), but until then how can I ignore them?
Upvotes: 11
Views: 1222
Reputation: 22962
Based on MrTristan's method. I think he mistakenly multiplied with screen scale.
+ (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;
}
Upvotes: 0
Reputation: 111
My solution was:
UIView* MYContentView=[[UIView alloc] initWithRect: CGrectMake:(0,0,Scrollview.frame.size.width, scrollview.frame.size.height)];
[ScrollView addsubview: MYContentView];
Then i added all the images to the MYContentView and later Rescaled the MYContentView and
[ScrollView setContentSize:Cgsize];
Now you can Enumerate all Images in the MYContentView without worrying about the scrollbars.
Doing:
while ([[MYContentView subviews] count]>0) {
[[[MYContentView subviews]lastObject] removeFromSuperview];
}
Removed only the images. Hope this helps
Upvotes: 0
Reputation: 71
This ended up being my work-around
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;
Upvotes: 7
Reputation: 740
i'm up against the same issue and i'm starting to think about looking at the values of those two UIImageView
s to figure out if its them or not. they do have a pretty unique signature:
<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>>
amongst other hooks that you could listen for. not ideal but not much in the way of options at this point...
heres an example. in this case, i was looping through the scrollview's subviews to figure out the optimal contentSize
height for the scrollview based on the subviews when it started coming out with some funky values which lead me to think that it was the scrollbars that were screwing with me...
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);
if checking the frame of each UIView isn't specific enough for you, you could also ensure that it is a UIImageView.
i'm thinking this is the only "true" solution at this point. i'd personally rather not have to maintain another array of views.
EDIT:
here's my consolidated method that i use:
-(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)));
}
Upvotes: 1
Reputation: 1173
Are the scroll indicator views added and removed throughout the lifetime of the scroll view, or are they just added once and hidden and shown as necessary? If it's the latter, you could store your own references to them in init... instead of using the private ivars and proceed as you have tried to already.
Upvotes: 0
Reputation: 27984
Presumably you're in control of the views that you put in the UIScrollView
. Why not maintain your own array of just those views? That way, you are safe against any future changes in the implementation of UIScrollView.
Upvotes: 2