iOS:导航栏的titleView在手机旋转时无法正确调整大小 [英] iOS: navigation bar's titleView doesn't resize correctly when phone rotates
问题描述
我正在编写一个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:
- 运行应用程序,手机保持纵向模式。一切看起来都不错。
- 做一些导致应用将另一个视图推送到导航堆栈的东西。例如。单击导致调用
的表行或按钮[self.navigationController pushViewController:someOtherViewController animated:YES]
。 - 查看子控制器,将手机旋转到横向。
- 单击返回按钮返回顶层视图。此时,标题视图混乱了:虽然您正在横向模式下拿着手机,但标题视图的大小仍然像在纵向模式下一样。
- 最后,将手机旋转回纵向模式。现在事情变得更糟了:标题视图缩小了(因为导航栏变小了),但由于它已经太小了,现在它太多太小了。
- Run the app, with the phone held in portrait mode. Everything looks good.
- 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]
. - While viewing the child controller, rotate the phone to landscape.
- 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.
- 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):
- 使用Xcode的基于导航的应用程序向导创建应用程序。
- 设置它以便顶级表视图具有行,当您单击时它们,将详细视图推送到导航堆栈。
-
在顶级视图控制器和详细视图控制器中包含此代码:
- Make an app using Xcode's "Navigation-based Application" wizard.
- 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.
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屋!