Reputation: 665
I have a UIViewController. The root UIView contains a custom UIScrollView I'm using for displaying thumbnail images in a grid (ThumbnailGrid class). This grid can contain a lot of UIViews which display images (GridTile class). Because there are so many grid tiles, the user can scroll down the ThumbnailGrid. I want to only load images for grid tiles which the user can actually see, I don't want to load ones for grid tiles which are off the edges of the screen.
How do I determine whether or not one of these GridTile UIViews is being displayed on the screen or not?
I've tried the following but it always seems to return false.
- (bool) isViewDisplayed:(UIView*)view
{
CGRect viewFrame = view.frame;
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
if (CGRectIntersectsRect(viewFrame, appFrame)) return true;
return false;
}
Am I missing something?
Thanks in advance for any help!
EDIT
THE SOLUTION
Turns out the coordinate systems were wrong, so I was getting some strange occurrences where the method should have returned true and instead it returned false, and vice versa.
- (bool) isViewDisplated:(UIView*)view
{
CGRect viewFrame = [parentOfView convertRect:view.frame toView:nil];
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
if (CGRectIntersectsRect(viewFrame, appFrame)) return true;
return false;
}
Upvotes: 3
Views: 662
Reputation: 7241
You also need to convert rect to the correct coordinate system:
- (bool)isViewDisplayed:(UIView*)view
{
if (view.window) {
CGRect viewFrame = [view.window convertRect:view.frame fromView:view.superview];
CGRect screenFrame = view.window.bounds;
return CGRectIntersectsRect(viewFrame, screenFrame);
}
return false;
}
Upvotes: 7
Reputation: 3399
You could do a compare like this:
NSMutableArray *outArray = [NSMutableArray array];
NSMutableArray *inArray = [NSMutableArray array];
for (UIView *vw in rootView.subViews){
if(vw.frame.origin.x <0 || vw.framew.origin.x >rootView.frame.size.width){
[outArray addObject:vw];
}else if(vw.frame.origin.y <0 || vw.framew.origin.y >rootView.frame.size.height){
[outArray addObject:vw];
}else{
[inArray addObject:vw];
}
}
So in the end your outArray will contain all the views which are partially/fully out of super view and inArray will have all those views which is completely inside the super view.
If you want to check for a single view using a method (say -(bool)isViewDisplayed:(UIView*)vw
), the same code inside the for loop would suffice, only thing is you would have to return true/false instead of adding to an array
PS: If you want to get only views completely out of your super view then instead of comparing against zero check against -vw.frame.size.width
& -vw.frame.size.height
.
Upvotes: 0
Reputation: 1876
Honestly, I think you are going about this the wrong way. There are a ton of existing frameworks designed to do exactly this. I don't know if I would spend the time to hand roll my own solution and handle all of the memory and view management. Check out this post: Grid of images in iOS
Upvotes: 0
Reputation: 25917
I know it doesn't directly answer your question, but still: why don't you use a UICollectionView
? It's able to handle most of the heavy parts for you. You don't have to care about the ones they are outside of the screen. You just to care about the behavior (delegation) and the content (data source).
Upvotes: 0
Reputation: 860
Make use of tags pretty easy to manage. something like this
UIView *view1 = [UIView]alloc]init];
view1.tag = 1;
[mainView addSubview:view1
];
and to check
UIView *temp = [mainView.view viewWithTag:1];
if(temp!=nil)return YES;
else NO;
see if this helps
Upvotes: -4