UIView final frame after device rotation

  • Hi,

      I have a hard time figuring out how to get the frame (in the window
    coordinate system) a view will rotate to, when the rotation has just begun.

    I'm observing UIApplicationDidChangeStatusBarFrameNotification on
    NSNotification's defaultCenter. When this notification is delivered, the
    rotation seems to be in progress. At that point I need to know the final frame
    the view is being rotated to.

    I've tried everything I could think of including these:

    r1 = [[view superview] convertRect:[view frame] toView:nil];
    r2 = [[view window] convertRect:[view bounds] fromView:view];
    r3 = [view convertRect:[view bounds] toView:nil];
    r4 = [[view window] convertRect:[[[view layer] modelLayer] frame] fromView:[view
    superview]];

    All get me the same results all the time (expected) but depending on the
    rotation direction and the previous orientation, I get nonsensical results like

    {{52, 0}, {268, 480}}

    or

    {{-80, 80}, {416, 320}}

    for a window-filling view (with a navigation bar visible). This led me to
    believe that I'm getting coordinates the view is set up to rotate from when the
    orientation changes. I can't for the life of me find a way to get the new frame
    that the view will have when the animation is complete.

    I feel like I'm missing something obvious, any ideas?

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
  • On Apr 2, 2013, at 10:59 AM, Markus Spoettl <ms_lists...> wrote:

    > I have a hard time figuring out how to get the frame (in the window coordinate system) a view will rotate to, when the rotation has just begun.

    What are you trying to do?

    Typically you don't need to worry about this. The root view controller's view will have its frame set properly by UIKit, and then all of your other views will resize with respect to that view's bounds, and as such you don't need to know how to get the final frame of that view.

    >
    > I'm observing UIApplicationDidChangeStatusBarFrameNotification on NSNotification's defaultCenter. When this notification is delivered, the rotation seems to be in progress. At that point I need to know the final frame the view is being rotated to.
    >
    > I've tried everything I could think of including these:
    >
    > r1 = [[view superview] convertRect:[view frame] toView:nil];
    > r2 = [[view window] convertRect:[view bounds] fromView:view];
    > r3 = [view convertRect:[view bounds] toView:nil];
    > r4 = [[view window] convertRect:[[[view layer] modelLayer] frame] fromView:[view superview]];
    >
    > All get me the same results all the time (expected) but depending on the rotation direction and the previous orientation, I get nonsensical results like
    >
    > {{52, 0}, {268, 480}}
    >
    > or
    >
    > {{-80, 80}, {416, 320}}
    >
    > for a window-filling view (with a navigation bar visible). This led me to believe that I'm getting coordinates the view is set up to rotate from when the orientation changes. I can't for the life of me find a way to get the new frame that the view will have when the animation is complete.
    >
    > I feel like I'm missing something obvious, any ideas?
    >
    > Regards
    > Markus
    > --
    > __________________________________________
    > Markus Spoettl

    --
    David Duncan
  • On 4/2/13 8:37 PM, David Duncan wrote:
    >> I have a hard time figuring out how to get the frame (in the window
    >> coordinate system) a view will rotate to, when the rotation has just
    >> begun.
    >
    > What are you trying to do?
    >
    > Typically you don't need to worry about this. The root view controller's view
    > will have its frame set properly by UIKit, and then all of your other views
    > will resize with respect to that view's bounds, and as such you don't need to
    > know how to get the final frame of that view.

    I'm displaying an overlay window which is "attached" to the view in question.
    When the rotation takes place, it needs to realign itself so that it's new
    location agrees with what the view displays (in my context).

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
  • On Apr 2, 2013, at 1:25 PM, Markus Spoettl <ms_lists...> wrote:

    > On 4/2/13 8:37 PM, David Duncan wrote:
    >>> I have a hard time figuring out how to get the frame (in the window
    >>> coordinate system) a view will rotate to, when the rotation has just
    >>> begun.
    >>
    >> What are you trying to do?
    >>
    >> Typically you don't need to worry about this. The root view controller's view
    >> will have its frame set properly by UIKit, and then all of your other views
    >> will resize with respect to that view's bounds, and as such you don't need to
    >> know how to get the final frame of that view.
    >
    > I'm displaying an overlay window which is "attached" to the view in question.

    I would think there might be an easier way to do this rather than using an overlay window, but I'm not entirely certain what your end goal is or what you are trying to overlay. You might consider an approach that uses view controller containment however.

    > When the rotation takes place, it needs to realign itself so that it's new location agrees with what the view displays (in my context).

    Have you tried doing this inside of -viewDidLayoutSubviews for the view controller that is managing all of this? That should be the best place to get the location of views after the layout has completed, although the animation information would need to be obtained seperately.
    --
    David Duncan
  • On Apr 2, 2013, at 13:25 , Markus Spoettl <ms_lists...> wrote:

    > I'm displaying an overlay window which is "attached" to the view in question. When the rotation takes place, it needs to realign itself so that it's new location agrees with what the view displays (in my context).

    Isn't it a mistake to tie this to rotation? IIRC there are other reasons the root view might be resized (e.g. squished to make room for the status bar or not? notifications?). You probably want to adjust your child view location in those cases too.

    IAC you might be safer to avoid using the frame. If there's a transform involved in the view's rotation, then the frame property will be meaningless. (But IDK if there's actually a transform applied to the view during rotation, or whether there's just a rotating animation.)
  • On 4/2/13 10:39 PM, David Duncan wrote:
    > On Apr 2, 2013, at 1:25 PM, Markus Spoettl <ms_lists...> wrote:
    >
    >> On 4/2/13 8:37 PM, David Duncan wrote:
    >>>> I have a hard time figuring out how to get the frame (in the window
    >>>> coordinate system) a view will rotate to, when the rotation has just
    >>>> begun.
    >>>
    >>> What are you trying to do?
    >>>
    >>> Typically you don't need to worry about this. The root view controller's
    >>> view will have its frame set properly by UIKit, and then all of your
    >>> other views will resize with respect to that view's bounds, and as such
    >>> you don't need to know how to get the final frame of that view.
    >>
    >> I'm displaying an overlay window which is "attached" to the view in
    >> question.
    >
    > I would think there might be an easier way to do this rather than using an
    > overlay window, but I'm not entirely certain what your end goal is or what
    > you are trying to overlay. You might consider an approach that uses view
    > controller containment however.

    Actually I did experiment with using embedded views instead of an overlay window
    but it was a lot easier to make "it" work that way. The overlay window lets us
    completely separate the overlay from the view's hierarchy.

    It would be an architectural problem to move that "into" the view hierarchy.

    >> When the rotation takes place, it needs to realign itself so that it's new
    >> location agrees with what the view displays (in my context).
    >
    > Have you tried doing this inside of -viewDidLayoutSubviews for the view
    > controller that is managing all of this? That should be the best place to get
    > the location of views after the layout has completed, although the animation
    > information would need to be obtained seperately. -- David Duncan

    No, I haven't tried that, not sure if you mean this would apply to an overlay
    solution. I'll see if I can figure out a way to use that.

    Still, there must be a way to get to the target view's frame before the
    animation is complete, no? When device rotation is complete, the view frame is
    correct. It's only ever "wrong" when the rotation notification is delivered.

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
  • On 4/2/13 10:53 PM, Quincey Morris wrote:
    > On Apr 2, 2013, at 13:25 , Markus Spoettl <ms_lists...>
    > <mailto:<ms_lists...>> wrote:
    >
    >> I'm displaying an overlay window which is "attached" to the view in question.
    >> When the rotation takes place, it needs to realign itself so that it's new
    >> location agrees with what the view displays (in my context).
    >
    > Isn't it a mistake to tie this to rotation? IIRC there are other reasons the
    > root view might be resized (e.g. squished to make room for the status bar or
    > not? notifications?). You probably want to adjust your child view location in
    > those cases too.
    >
    > IAC you might be safer to avoid using the frame. If there's a transform involved
    > in the view's rotation, then the frame property will be meaningless. (But IDK if
    > there's actually a transform applied to the view during rotation, or whether
    > there's just a rotating animation.)

    Not sure if I understand what you're saying, but if that was the case, the
    view's frame I'm attaching the overlay to would turn out wrong if the device is
    rotated.

    The only time I get a bogus view frame is when the rotation notification is
    delivered. If I wait for the rotation to complete and get the frame then, it's
    correct (no matter which orientation the device has been rotated to). Only, it's
    useless as I have to rotate the overlay alongside the main window, so before the
    rotation is complete.

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
  • On Apr 2, 2013, at 14:21 , Markus Spoettl <ms_lists...> wrote:

    > Not sure if I understand what you're saying, but if that was the case, the view's frame I'm attaching the overlay to would turn out wrong if the device is rotated.

    No, once the rotation is complete (at least), there'd be no transform any more, and so the frame would then be valid.

    I looked at what happens when I rotate iBooks from portrait to landscape on an iPad (a +90 degree rotation), and this is what I see:

    1. The view changes from portrait layout to landscape layout, but is displayed so the text is still in portrait orientation. In other words, the view behaves *as if* it immediately resizes to its final landscape orientation bounds, and is immediately displayed with a -90 degree rotation relative to landscape orientation, which "preserves" the original text orientation.

    2. The view animates the rotation to landscape.  That is, the view appears to animate its rotation smoothly from -90 degrees up to 0 degrees, relative to landscape orientation. (There may also be a scaling involved here, I couldn't quite tell since it all happens so fast. If there is one, it also ends at 100%.)

    3. At that time, the transformation is the identity transformation.

    If the rotation notification is sent after step 1, the view frame is meaningless until step 3.

    > The only time I get a bogus view frame is when the rotation notification is delivered.

    It would be easy to try examining the "bounds" and "center" properties at the time of the notification, and see whether *they* are bogus. If not, you should be able to orient your child view using those two properties, instead of using "frame".
  • On 4/3/13 12:47 AM, Quincey Morris wrote:
    > On Apr 2, 2013, at 14:21 , Markus Spoettl <ms_lists...>
    > <mailto:<ms_lists...>> wrote:
    >
    >> Not sure if I understand what you're saying, but if that was the case, the
    >> view's frame I'm attaching the overlay to would turn out wrong if the device
    >> is rotated.
    >
    > No, once the rotation is complete (at least), there'd be no transform any more,
    > and so the frame would then be valid.

    Ah, OK you're right.

    >> The only time I get a bogus view frame is when the rotation notification is
    >> delivered.
    >
    > It would be easy to try examining the "bounds" and "center" properties at the
    > time of the notification, and see whether *they* are bogus. If not, you should
    > be able to orient your child view using those two properties, instead of using
    > "frame".

    bounds and center are correct at all times. However, I need the view's frame in
    screen coordinates because I'm positioning an independent overlay window, not a
    subview. Since the transformation messes with -convertRect:from/toView: in my
    view hierarchy, I have no idea how to get to the frame I'm interested in. Any ideas?

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
  • On Apr 3, 2013, at 00:16 , Markus Spoettl <ms_lists...> wrote:

    > bounds and center are correct at all times. However, I need the view's frame in screen coordinates because I'm positioning an independent overlay window, not a subview. Since the transformation messes with -convertRect:from/toView: in my view hierarchy, I have no idea how to get to the frame I'm interested in. Any ideas?

    It might be easier just not to work with the frame at all. I suspect you can use 'convertPoint:…' on the center to get to the coordinate system you need for the attached view, then use that and the bounds to compute the attached view's center and bounds.
  • On 4/3/13 6:42 PM, Quincey Morris wrote:
    >> bounds and center are correct at all times. However, I need the view's frame
    >> in screen coordinates because I'm positioning an independent overlay window,
    >> not a subview. Since the transformation messes with -convertRect:from/toView:
    >> in my view hierarchy, I have no idea how to get to the frame I'm interested
    >> in. Any ideas?
    >
    > It might be easier just not to work with the frame at all. I suspect you can use
    > 'convertPoint:…' on the center to get to the coordinate system you need for the
    > attached view, then use that and the bounds to compute the attached view's
    > center and bounds.

    I'll try that, thanks for the suggestion!

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
previous month april 2013 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
Go to today