iOS:导航栏的titleView在手机旋转时无法正确调整大小 [英] iOS: navigation bar's titleView doesn't resize correctly when phone rotates

查看:98
本文介绍了iOS:导航栏的titleView在手机旋转时无法正确调整大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个iPhone应用程序(与大多数应用程序一样)支持自动旋转:您可以旋转手机,其视图可以旋转并适当调整大小。

I'm writing an iPhone app that (like most apps) supports auto-rotation: You rotate your phone, and its views rotate and resize appropriately.

但是我正在为 navigationItem.titleView (导航栏的标题区域)分配自定义视图,当手机旋转时,我无法正确调整视图大小。

But I am assigning a custom view to navigationItem.titleView (the title area of the navigation bar), and I can't get that view to resize correctly when the phone rotates.

我知道你在想什么,只需将 autoresizingMask 设置为 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ,但事情并非那么简单。当然,如果我没有设置我的视图 autoresizingMask ,那么我的视图不会调整大小;我希望它能够调整大小。

I know what you're thinking, "Just set its autoresizingMask to UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight," but it's not that simple. Of course, if I don't set my view's autoresizingMask, then my view doesn't resize; and I want it to resize.

问题是,如果我设置其 autoresizingMask ,只要该视图可见,它就会正确调整大小;但 titleView 的大小在这种情况下搞砸了:

The problem is, if I do set its autoresizingMask, then it resizes correctly as long as that view is visible; but the titleView's size gets messed up in this scenario:


  1. 运行应用程序,手机保持纵向模式。一切看起来都不错。

  2. 做一些导致应用将另一个视图推送到导航堆栈的东西。例如。单击导致调用的表行或按钮[self.navigationController pushViewController:someOtherViewController animated:YES]

  3. 查看子控制器,将手机旋转到横向。

  4. 单击返回按钮返回顶层视图。此时,标题视图混乱了:虽然您正在横向模式下拿着手机,但标题视图的大小仍然像在纵向模式下一样。

  5. 最后,将手机旋转回纵向模式。现在事情变得更糟了:标题视图缩小了(因为导航栏变小了),但由于它已经太小了,现在它太多太小了。

  1. Run the app, with the phone held in portrait mode. Everything looks good.
  2. Do something that causes the app to push another view onto the navigation stack. E.g. click a table row or button that causes a call to [self.navigationController pushViewController:someOtherViewController animated:YES].
  3. While viewing the child controller, rotate the phone to landscape.
  4. Click the "Back" button to return to the top-level view. At this point, the title view is messed up: Although you are holding the phone in landscape mode, the title view is still sized as if you were holding it in portrait mode.
  5. Finally, rotate the phone back to portrait mode. Now things get even worse: The title view shrinks in size (since the navigation bar got smaller), but since it was already too small, now it is much too small.

如果您想自己重现,请按照以下步骤操作(这有点工作):

If you want to reproduce this yourself, follow these steps (this is a bit of work):


  1. 使用Xcode的基于导航的应用程序向导创建应用程序。

  2. 设置它以便顶级表视图具有行,当您单击时它们,将详细视图推送到导航堆栈。

  3. 在顶级视图控制器和详细视图控制器中包含此代码:

  1. Make an app using Xcode's "Navigation-based Application" wizard.
  2. Set it up so that the top-level table view has rows that, when you click them, push a detail view onto the navigation stack.
  3. Include this code in both the top-level view controller and the detail view controller:

- (BOOL)shouldAutorotateToInterfaceOrientation:
        (UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}


  • 仅在顶级视图控制器中包含此代码:

  • Include this code in only the top-level view controller:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // Create "Back" button
        UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Master"
            style:UIBarButtonItemStylePlain target:nil action:nil];
        self.navigationItem.backBarButtonItem = backButton;
        [backButton release];
    
        // Create title view
        UILabel* titleView = [[[UILabel alloc] initWithFrame:CGRectMake(0,0,500,38)] autorelease];
        titleView.textAlignment = UITextAlignmentCenter;
        titleView.text = @"Watch this title view";
    
        // If I leave the following line turned on, then resizing of the title view
        // messes up if I:
        //
        // 1. Start at the master view (which uses this title view) in portrait
        // 2. Navigate to the detail view
        // 3. Rotate the phone to landscape
        // 4. Navigate back to the master view
        // 5. Rotate the phone back to portrait
        //
        // On the other hand, if I remove the following line, then I get a different
        // problem: The title view doesn't resize as I want it to when I:
        //
        // 1. Start at the master view (which uses this title view) in portrait
        // 2. Rotate the phone to landscape
        titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    
        self.navigationItem.titleView = titleView;
    }
    


  • 最后,按照我的重复步骤。

  • Finally, follow my repro steps.

    所以...我做错了什么?有没有办法让我的titleView始终正确调整大小?

    So ... am I doing something wrong? Is there a way to make my titleView always resize correctly?

    推荐答案

    (回答我自己的问题)

    我通过手动跟踪titleView的边距(它与导航栏边缘的距离)来实现这一点 - 在视图消失时保存,并在视图重新出现时恢复。

    I got this working by manually keeping track of the titleView's margins (its distance from the edges of the navigtion bar) -- saving when the view disappears, and restoring when the view reappears.

    我们的想法是,我们不会将titleView恢复到之前的确切大小;相反,我们正在恢复它,以便它具有与之前相同的边距。这样,如果手机已旋转,则titleView将具有新的适当大小。

    The idea is, we aren't restoring the titleView to the exact size it had previously; rather, we are restoring it so that it has the same margins it had previously. That way, if the phone has rotated, the titleView will have a new, appropriate size.

    这是我的代码:

    在我的视图中控制器的.h文件:

    In my view controller's .h file:

    @interface MyViewController ...
    {
        CGRect titleSuperviewBounds;
        UIEdgeInsets titleViewMargins;
    }
    

    在我的视图控制器的.m文件中:

    In my view controller's .m file:

    /**
     * Helper function: Given a parent view's bounds and a child view's frame,
     * calculate the margins of the child view.
     */
    - (UIEdgeInsets) calcMarginsFromParentBounds:(CGRect)parentBounds
                                      childFrame:(CGRect)childFrame {
        UIEdgeInsets margins;
        margins.left = childFrame.origin.x;
        margins.top = childFrame.origin.y;
        margins.right = parentBounds.size.width -
            (childFrame.origin.x + childFrame.size.width);
        margins.bottom = parentBounds.size.height -
            (childFrame.origin.y + childFrame.size.height);
        return margins;
    }
    
    - (void)viewDidUnload {
        [super viewDidUnload];
    
        titleSuperviewBounds = CGRectZero;
        titleViewMargins = UIEdgeInsetsZero;
    }
    
    - (void) viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
    
        // Keep track of bounds information, so that if the user changes the
        // phone's orientation while we are in a different view, then when we
        // return to this view, we can fix the titleView's size.
        titleSuperviewBounds = self.navigationItem.titleView.superview.bounds;
        CGRect titleViewFrame = self.navigationItem.titleView.frame;
        titleViewMargins = [self calcMarginsFromParentBounds:titleSuperviewBounds
                                                  childFrame:titleViewFrame];
    }
    
    
    - (void) viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
    
        // Check for the case where the user went into a different view, then
        // changed the phone's orientation, then returned to this view.  In that
        // case, our titleView probably has the wrong size, and we need to fix it.
        if (titleSuperviewBounds.size.width > 0) {
            CGRect newSuperviewBounds =
                self.navigationItem.titleView.superview.bounds;
            if (newSuperviewBounds.size.width > 0 &&
                !CGRectEqualToRect(titleSuperviewBounds, newSuperviewBounds))
            {
                CGRect newFrame = UIEdgeInsetsInsetRect(newSuperviewBounds,
                    titleViewMargins);
                newFrame.size.height =
                    self.navigationItem.titleView.frame.size.height;
                newFrame.origin.y = floor((newSuperviewBounds.size.height -
                    self.navigationItem.titleView.frame.size.height) / 2);
                self.navigationItem.titleView.frame = newFrame;
            }
        }
    }
    

    这篇关于iOS:导航栏的titleView在手机旋转时无法正确调整大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆