iPhone correct landscape window coordinates
Asked Answered
F

5

8

I am trying to get the window coordinates of a table view using the following code:

[self.tableView.superview convertRect:self.tableView.frame toView:nil]

It reports the correct coordinates while in portrait mode, but when I rotate to landscape it no longer reports correct coordinates. First off, it flips the x, y coordinates and the width and height. That's not really the problem though. The real problem is that the coordinates are incorrect. In portrait the window coordinates for the table view's frame are {{0, 114}, {320, 322}}, while in landscape the window coordinates are {{32, 0}, {204, 480}}. Obviously the x-value here is incorrect, right? Shouldn't it be 84? I'm looking for a fix to this problem, and if anybody knows how to get the correct window coordinates of a view in landscape mode, I would greatly appreciate it if you would share that knowledge with me.

Here are some screenshots so you can see the view layout.

Portrait: https://i.sstatic.net/IaKJc.png

Landscape: https://i.sstatic.net/JHUV6.png

Flora answered 17/5, 2011 at 17:16 Comment(1)
I'm seeing the same problem. Sometimes it correctly calculates coordinates, sometimes it doesn't.Unbounded
U
6

I've found what I believe to be the beginnings of the solution. It seems the coordinates you and I are seeing are being based on the bottom left or top right, depending on whether the orientation is UIInterfaceOrientationLandscapeRight or UIInterfaceOrientationLandscapeLeft.

I don't know why yet, but hopefully that helps. :)

[UPDATE] So I guess the origin of the window is 0,0 in normal portrait mode, and rotates with the ipad/iphone.

So here's how I solved this.

First I grab my orientation, window bounds and the rect of my view within the window (with the wonky coordinates)

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect windowRect = appDelegate.window.bounds;
CGRect viewRectAbsolute = [self.guestEntryTableView convertRect:self.guestEntryTableView.bounds toView:nil];

Then if the orientation is landscape, I reverse the x and y coordinates and the width and height

if (UIInterfaceOrientationLandscapeLeft == orientation ||UIInterfaceOrientationLandscapeRight == orientation ) {
    windowRect = XYWidthHeightRectSwap(windowRect);
    viewRectAbsolute = XYWidthHeightRectSwap(viewRectAbsolute);
}

Then I call my function for fixing the origin to be based on the top left no matter the rotation of the ipad/iphone. It fixes the origin depending on where 0,0 currently lives (depending on the orientation)

viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation, windowRect.size.width, windowRect.size.height);

Here are the two functions I use

CGRect XYWidthHeightRectSwap(CGRect rect) {
    CGRect newRect;
    newRect.origin.x = rect.origin.y;
    newRect.origin.y = rect.origin.x;
    newRect.size.width = rect.size.height;
    newRect.size.height = rect.size.width;
    return newRect;
}

CGRect FixOriginRotation(CGRect rect, UIInterfaceOrientation orientation, int parentWidth, int parentHeight) {
    CGRect newRect;
    switch(orientation)
    {
        case UIInterfaceOrientationLandscapeLeft:
            newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), rect.origin.y, rect.size.width, rect.size.height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            newRect = CGRectMake(rect.origin.x, parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
            break;
        case UIInterfaceOrientationPortrait:
            newRect = rect;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
            break;
    }
    return newRect;
}
Unbounded answered 19/7, 2011 at 7:46 Comment(0)
S
3

This is a hack, but it works for me:

UIView *toView = [UIApplication sharedApplication].keyWindow.rootViewController.view;
[self.tableView convertRect:self.tableView.bounds toView:toView];

I am not sure this is the best solution. It may not work reliably if your root view controller doesn't support the same orientations as the current view controller.

Sevenup answered 3/2, 2014 at 21:1 Comment(0)
O
0

You should be able to get the current table view coordinates from self.tableView.bounds

Owlish answered 17/5, 2011 at 19:36 Comment(0)
G
0

Your code should be:

[tableView convertRect:tableView.bounds toView:[UIApplication sharedApplication].keyWindow];

That will give you the view's rectangle in the window's coordinate system. Be sure to use "bounds" and not "frame". frame is the rectangle of the view in its parent view coordinate system already. "bounds" is the view rectangle in its own system. So the above code asks the table view to convert its own rectangle from its own system to the window's system. Your previous code was asking the table's parent view to convert the table's rectangle from the parent coordinate system to nothing.

Gingras answered 17/5, 2011 at 20:3 Comment(1)
Actually, the documentation for convertRect:toView: says, "If view is nil, this method instead converts to window base coordinates." I tried your code and it gives the same result as mine. Thanks though for the suggestion.Flora
H
0

Try bounds instead of frame self.parentViewController.view.bounds for it gives me adjusted coords according to the current orientation

Handbook answered 24/1, 2012 at 10:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.