34

これは、人々が私にガイダンスを提供するためのより一般的な質問です.基本的に私はiPad/iPhone開発を学んでおり、最終的に多方向サポートの質問に出くわしました.

私はかなりの数の doco を調べましたが、私の著書「Beginning iPhone 3 Development」には、それに関する素晴らしい章があります。

しかし、私の質問は、プログラムでコントロールを変更する場合 (または方向ごとに異なるビューを使用する場合) は、一体どうやってコード ベースを維持するのでしょうか? スパゲッティ コード/何千もの "if" チェックに関する非常に多くの問題がいたるところにあることは想像に難くありません。

この問題を処理した経験のある人はいますか? それを制御するための良い方法は何ですか?

どうもありがとうマーク

4

6 に答える 6

41

ビュー コントローラーで 2 つの簡単なメソッドを使用してこれを行います。

- (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 設定アプリケーションを見ると、レイアウトにテーブル ビューが使用され、ほとんどの行にカスタム セルが使用されていることがわかります。これにより、セルの幅を埋めるだけで、単純なインターフェイスをかなり安価に回転させることができます。これは、各行に編集テキスト セルがある Mail のようなものにも当てはまります。また、テーブルは簡単にすべて透明にすることができ、ボタンまたはラベルのみが表示されるため、テーブルのようには見えません。

すべての UIView の autoresizingMask から多くのマイレージを取得できます。柔軟な高さを持つアイテムが 1 つ以上ある場合、通常、どちらの向きでも適切に見えるインターフェイス レイアウトを取得できます。見た目によっては、すべてを一番上に固定できる場合もあります。

まれに、すべてのインターフェイス要素が正方形に収まる場合は、その場で回転させることができます。

向きの変更を明示的に処理する必要がある場合が 2 つあります。1 つは、回転時にビューが別のビューの横から下に移動する場合です。もう 1 つは、常に全幅にしたい場合など、向きごとに異なる画像がある場合です。

これらの両方を回避する方法がある場合があります。伸縮可能な画像を使用するか、1 行につき 1 つのビューに制限することができます。または、特定のビューの方向をロックアウトする場合があります。

ビューのレイアウトを変更する必要がある場合は、明示的な layoutSubviews メソッドがあります。この 1 つのメソッドですべての条件付きレイアウトを処理するようにしてください。これは、ビューの境界が変更された場合 (回転時やキーボード用のスペースを確保した場合など) にのみ呼び出されます。回転に対応する必要があるビュー階層ごとにカスタム ビューを作成し、そこからサブビューをレイアウトします。

于 2010-05-12T03:26:54.343 に答える
2

iPhone SDK は MVC アーキテクチャを中心に構築されているため、理論的には、すべてのロジック (モデル) を UI (ビュー) から分離しておくと、UI の 1 つの場所 (ビュー コントローラー) だけを気にする必要があります。それらについては、向きごとに個別のView Controllerを用意し、それぞれに1つのif/elseをロードして、ロードするView Controllerを選択することができます。

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

あなたの質問では、次のように書いています。

スパゲッティ コード/何千もの "if" チェックに関する非常に多くの問題がいたるところにあることは想像に難くありません。

これを回避する 1 つの方法は、iPhone/iPad 固有の変更の処理を最初から分割するビュー階層を作成することです。デバイスごとに最初にロードするビューを設定するだけで済みます。次に、通常どおりビューコントローラーを作成しますが、作成したビューコントローラーをサブクラス化します。デバイスごとに 1 つのサブクラス。向きの処理など、デバイス固有のコードを配置できる場所です。このような:

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

このアプローチに興味がある場合は、この記事を読むことをお勧めします。とても親切に説明してくれます。

この記事で言及されていることの1つは、次のとおりです。

--引用開始--

このパターンの優れた点は、次のようなくだらないコードでコードを散らかす必要がないことです。

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 に答える