这更像是一个一般性的问题,供人们为我提供指导,基本上我正在学习 iPad/iPhone 开发,终于遇到了多方向支持问题。
我查阅了相当多的 doco,我的书“开始 iPhone 3 开发”中有一个很好的章节。
但我的问题是,如果我要以编程方式更改我的控件(甚至对每个方向使用不同的视图),人们究竟如何维护他们的代码库?我可以想象意大利面条代码/数以千计的“如果”检查到处都是这么多问题,这会让我疯狂地对 UI 安排进行一点小改动。
有没有人有处理这个问题的经验?什么是控制它的好方法?
非常感谢马克
这更像是一个一般性的问题,供人们为我提供指导,基本上我正在学习 iPad/iPhone 开发,终于遇到了多方向支持问题。
我查阅了相当多的 doco,我的书“开始 iPhone 3 开发”中有一个很好的章节。
但我的问题是,如果我要以编程方式更改我的控件(甚至对每个方向使用不同的视图),人们究竟如何维护他们的代码库?我可以想象意大利面条代码/数以千计的“如果”检查到处都是这么多问题,这会让我疯狂地对 UI 安排进行一点小改动。
有没有人有处理这个问题的经验?什么是控制它的好方法?
非常感谢马克
我在视图控制器中使用两种简单的方法来做到这一点:
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self adjustViewsForOrientation:toInterfaceOrientation];
}
- (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation {
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
titleImageView.center = CGPointMake(235.0f, 42.0f);
subtitleImageView.center = CGPointMake(355.0f, 70.0f);
...
}
else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
titleImageView.center = CGPointMake(160.0f, 52.0f);
subtitleImageView.center = CGPointMake(275.0f, 80.0f);
...
}
}
为了保持干净,您可以轻松地划分视图调整/重新加载/等。if-else使用从单个条件内部调用的方法。
这实际上取决于您要布置的内容。
如果您查看 Apple Settings 应用程序,您会发现他们使用表格视图进行布局,大多数行都使用自定义单元格。有了它,您可以通过填充单元格的宽度来允许简单的界面非常便宜地旋转。这甚至适用于邮件之类的东西,每行都有编辑文本单元格。而且表格很容易全部透明,只有按钮或标签可见,因此它们看起来不像表格。
你可以从每个 UIView 的 autoresizingMask 中获得很多好处。如果您有一个或多个可以具有灵活高度的项目,那么您通常可以获得在任一方向看起来都不错的界面布局。根据它的外观,有时您可以将所有内容固定在顶部。
在极少数情况下,如果所有界面元素都适合一个正方形,您可以将它们旋转到位。
有两次您必须明确处理方向更改。一种是当一个视图在旋转时从另一个旁边移动到下面。另一种是当您为每个方向都有不同的图像时,例如,如果您总是想要全宽。
有时有一些方法可以解决这两种情况。您可以使用可拉伸图像或将自己限制为每行一个视图。或者您可能会锁定某些视图的方向。
如果你必须改变视图的布局,有一个显式的 layoutSubviews 方法。您应该尝试在这一种方法中处理所有条件布局。它仅在视图边界发生变化时调用,例如在旋转时或您为键盘腾出空间时。为每个需要响应旋转的视图层次结构创建一个自定义视图,并从那里布局子视图。
iPhone SDK 是围绕 MVC 架构构建的,因此理论上如果您将所有逻辑(模型)与 UI(视图)分开,那么您只需要在一个地方担心 UI:您的视图控制器。对于那些,您可以为每个方向都有一个单独的视图控制器,然后每个方向都将加载一个 if/else 以选择要加载的视图控制器。
iPhone / iPad 支持同样的想法,您可以在其中加载另一个可以处理更大显示器的视图控制器。
我不能保证这段代码,老实说,上面的 willRotateToInterfaceOrientation 效果很好。这是来自 Facebook 的 FBDialog.m 用于 iphone / ipad 的另一种看法。(虽然,我认为这是一个网络视图)
这是要点
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceOrientationDidChange:)
name:@"UIDeviceOrientationDidChangeNotification" object:nil];
- (void)deviceOrientationDidChange:(void*)object {
UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if ([self shouldRotateToOrientation:orientation]) {
CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
[self sizeToFitOrientation:YES];
[UIView commitAnimations];
}
}
-(CGAffineTransform)transformForOrientation {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (orientation == UIInterfaceOrientationLandscapeLeft) {
return CGAffineTransformMakeRotation(M_PI*1.5);
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
return CGAffineTransformMakeRotation(M_PI/2);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
return CGAffineTransformMakeRotation(-M_PI);
} else {
return CGAffineTransformIdentity;
}
}
- (void)sizeToFitOrientation:(BOOL)transform {
if (transform) {
self.transform = CGAffineTransformIdentity;
}
CGRect frame = [UIScreen mainScreen].applicationFrame;
CGPoint center = CGPointMake(
frame.origin.x + ceil(frame.size.width/2),
frame.origin.y + ceil(frame.size.height/2));
CGFloat scale_factor = 1.0f;
if (FBIsDeviceIPad()) {
// On the iPad the dialog's dimensions should only be 60% of the screen's
scale_factor = 0.6f;
}
CGFloat width = floor(scale_factor * frame.size.width) - kPadding * 2;
CGFloat height = floor(scale_factor * frame.size.height) - kPadding * 2;
_orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsLandscape(_orientation)) {
self.frame = CGRectMake(kPadding, kPadding, height, width);
} else {
self.frame = CGRectMake(kPadding, kPadding, width, height);
}
self.center = center;
if (transform) {
self.transform = [self transformForOrientation];
}
}
在您的问题中,您写道:
我可以想象意大利面条代码/数以千计的“如果”检查到处都是这么多问题,这会让我疯狂地对 UI 安排进行一点小改动。
避免这种情况的一种方法是创建一个视图层次结构,从一开始就拆分 iPhone/iPad 特定更改的处理。您只需设置最初为每个设备加载的视图。然后你像往常一样创建一个视图控制器,但你也继承了你创建的视图控制器。每个设备一个子类。那是您可以放置设备特定代码的地方,例如方向处理。像这样:
MyViewController.h // Code that is used on both devices
MyViewController_iPhone.h // iPhone specific code, like orientation handling
MyViewController_iPad.h // iPad specific code, like orientation handling
如果您对这种方法感兴趣,我建议您阅读这篇文章。它以非常好的方式解释它。
文章提到的一件事是:
--报价开始--
这种模式的美妙之处在于我们不必在代码中乱扔垃圾,看起来像这样:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// The device is an iPad running iPhone 3.2 or later.
// set up the iPad-specific view
} else {
// The device is an iPhone or iPod touch.
// set up the iPhone/iPod Touch view
}
---报价结束---
我希望这会有所帮助。祝你好运!