David Omid
David Omid

Reputation: 665

Is UIView being displayed?

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

Answers (5)

Mark Kryzhanouski
Mark Kryzhanouski

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

Rakesh
Rakesh

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

JiuJitsuCoder
JiuJitsuCoder

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

Rui Peres
Rui Peres

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

Prajwal Udupa
Prajwal Udupa

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

Related Questions