34

这更像是一个一般性的问题,供人们为我提供指导,基本上我正在学习 iPad/iPhone 开发,终于遇到了多方向支持问题。

我查阅了相当多的 doco,我的书“开始 iPhone 3 开发”中有一个很好的章节。

但我的问题是,如果我要以编程方式更改我的控件(甚至对每个方向使用不同的视图),人们究竟如何维护他们的代码库?我可以想象意大利面条代码/数以千计的“如果”检查到处都是这么多问题,这会让我疯狂地对 UI 安排进行一点小改动。

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

非常感谢马克

4

6 回答 6

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

为了保持干净,您可以轻松地划分视图调整/重新加载/等。if-else使用从单个条件内部调用的方法。

于 2010-05-12T02:39:46.543 回答
7

这实际上取决于您要布置的内容。

如果您查看 Apple Settings 应用程序,您会发现他们使用表格视图进行布局,大多数行都使用自定义单元格。有了它,您可以通过填充单元格的宽度来允许简单的界面非常便宜地旋转。这甚至适用于邮件之类的东西,每行都有编辑文本单元格。而且表格很容易全部透明,只有按钮或标签可见,因此它们看起来不像表格。

你可以从每个 UIView 的 autoresizingMask 中获得很多好处。如果您有一个或多个可以具有灵活高度的项目,那么您通常可以获得在任一方向看起来都不错的界面布局。根据它的外观,有时您可以将所有内容固定在顶部。

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

有两次您必须明确处理方向更改。一种是当一个视图在旋转时从另一个旁边移动到下面。另一种是当您为每个方向都有不同的图像时,例如,如果您总是想要全宽。

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

如果你必须改变视图的布局,有一个显式的 layoutSubviews 方法。您应该尝试在这一种方法中处理所有条件布局。它仅在视图边界发生变化时调用,例如在旋转时或您为键盘腾出空间时。为每个需要响应旋转的视图层次结构创建一个自定义视图,并从那里布局子视图。

于 2010-05-12T03:26:54.343 回答
2

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

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

于 2010-05-12T02:35:27.843 回答
1

请参阅以下链接: http: //mustafashaik.wordpress.com/2010/11/17/handling-orientations-in-ipad/

于 2010-11-17T08:07:39.753 回答
0

我不能保证这段代码,老实说,上面的 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];
  }
}
于 2011-11-26T10:27:34.717 回答
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

如果您对这种方法感兴趣,我建议您阅读这篇文章。它以非常好的方式解释它。

文章提到的一件事是:

--报价开始--

这种模式的美妙之处在于我们不必在代码中乱扔垃圾,看起来像这样:

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
}

---报价结束---

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

于 2011-11-26T11:02:15.753 回答