2010-05-12 53 views
34

这是一个人们为我提供指导的一般问题,基本上我在学习iPad/iPhone开发,并最终遇到了多方向支持问题。iphone/ipad方向处理

我已经查找了相当数量的doco,而我的书“Beginning iPhone 3 Development”有一个很好的章节。

但我的问题是,如果我想以编程方式更改我的控件(或者甚至针对每个方向使用不同的视图),人们如何维护其代码库?我可以想象如此多的意大利面条代码/成千上万的“if”检查问题,它会迫使我对UI界面做一些小改动。

有没有人有处理这个问题的经验?什么是控制它的好方法?

非常感谢 马克

回答

41

我做到这一点,在我的视图控制器两种简单的方法:

- (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); 
     ... 
    } 
} 

为了保持干净,你可以很容易地划分视图调整/重装/等。使用从单个条件中调用的方法。

+0

是的,这是有点什么即时通讯现在做...感谢 – Mark 2010-05-12 02:56:53

+1

对我willRotateToInterface方法永远不会被调用。你需要连接一些东西,或者在IB中添加一个监听器吗? – 2010-08-13 00:38:26

+0

这是我正在寻找的很好的例子。任何替代的例子? – 2010-12-16 09:50:07

2

,如果你把你所有的从你的UI(视图)分开的逻辑(模型)的iPhone SDK是围绕在理论上有一个MVC架构,因此建那么你只需要担心关于一个地方的用户界面:你的视图控制器。对于那些,你可以有一个单独的视图控制器为每个方向,其中每一个然后将被加载一个if/else来选择加载哪个视图控制器。

对于iPhone/iPad支持,您可以加载另一个可以处理更大显示的视图控制器的相同想法。

+0

是的,我曾见过有人做这样的事情,它是一个好主意,谢谢 – Mark 2010-05-12 02:57:51

7

这真的取决于你在铺设什么。

如果您查看Apple Settings应用程序,您可以看到他们使用表格视图作为布局,并为大多数行定制了单元格。这样,您可以通过填充单元格的宽度,以简单的界面进行相当便宜的旋转。这甚至适用于邮件,每行都有编辑文本单元的东西。表格可以很容易地全部透明,只有按钮或标签可见,所以它们看起来不像表格。

您可以从每个UIView的autoresizingMask中获得大量的milage。如果您有一个或多个项目可以具有灵活的高度,那么通常可以获得在任一方向都看起来很好的界面布局。根据它的外观,有时候你可以把所有东西都放在最上面。

在极少数情况下,如果所有界面元素都放在正方形中,您可以将它们旋转到位。

有两次您必须明确处理方向更改。一种是在旋转时视图从旁边移动到另一个之下。另一种情况是每个方向都有不同的图像,例如,如果您始终希望成为全幅图像。

有时会有解决这两个问题的方法。您可以使用可拉伸图像或将自己限制为每行一个视图。或者您可以锁定某些视图的方向。

如果您必须更改视图的布局,则会有一个明确的layoutSubviews方法。你应该尝试在这个方法中处理你所有的条件布局。只有当视图边界发生变化时才会调用它,例如在旋转时或如果您为键盘腾出空间。为需要响应旋转的每个视图层次结构进行自定义视图,并从中布局子视图。

0

我不能保证这些代码,并在所有诚实上述willRotateToInterfaceOrientation的伟大工程。这里是另一个与Facebook的FBDialog.m对iphone/ipad的采访。 (虽然,我认为这是对的WebView)

这里的要点

[[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]; 
    } 
} 
0

在你的问题,你写道:

我可以想像的细码/十万这么多问题的“如果”检查遍布整个地方,它会迫使我坚决对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 

如果你有兴趣在此方法中,我建议你读this article。它以非常好的方式解释它。

之一上述文章中提到的事情,是这样的:

的quote--

这种模式的好处是--start我们没有垃圾我们的代码是废话看起来是这样的:

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 
} 

---年底quote--

我希望有所帮助。祝你好运!