【问题标题】:iphone/ipad orientation handlingiphone/ipad 方向处理
【发布时间】:2010-05-12 02:26:41
【问题描述】:

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

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

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

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

非常感谢 标记

【问题讨论】:

    标签: iphone ipad screen-orientation


    【解决方案1】:

    我在视图控制器中使用两个简单的方法来做到这一点:

    - (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 条件内部调用的方法。

    【讨论】:

    • 永远不会调用我的 willRotateToInterface 方法。您是否必须在 IB 中连接某些东西或添加侦听器之类的东西?
    • 这是我一直在寻找的好例子。还有其他例子吗?
    • 我无法调用 willRotateToInterface ,我正在查看每个帖子。为什么它不起作用?
    • 您正在实施? -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ return YES; }
    • 我在我的代码中使用了完全相同的方法,而且它工作得很好——只要你真的改变方向。也就是说,只要从 willRotateToInterfaceOrientation 中调用adjustViewsForOrientation 之类的,就可以了。但是,如果您在 设备已经处于该方向时呈现视图,则将(显然)不会调用 willRotateToInterfaceOrientation。我尝试了 viewWillAppear 和 viewDidAppear - 但在这两种情况下,设置子视图中心的后续分配似乎都没有效果。关于如何解决这个问题的任何想法?
    【解决方案2】:

    这真的取决于你要布置什么。

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 是的,我见过有人这样做,这是个好主意,谢谢
      【解决方案4】:
      【解决方案5】:

      我不能保证这段代码,老实说,上面的 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];
        }
      }
      

      【讨论】:

        【解决方案6】:

        在你的问题中,你写道:

        我可以想象,意大利面条式代码/成千上万的“如果”检查到处都有这么多问题,这会让我抓狂地对 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。它以非常好的方式解释了它。

        文章提到的一件事是:

        --引用开始--

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

        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-03-08
          • 2012-08-17
          • 2012-09-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-18
          相关资源
          最近更新 更多