управление ориентацией iphone / ipad - PullRequest
34 голосов
/ 12 мая 2010

Это более общий вопрос для людей, чтобы дать мне руководство, в основном я изучаю разработку для iPad / iPhone и наконец столкнулся с вопросом поддержки мульти-ориентации.

Я искал изрядное количествоо doco, и моя книга «Начало разработки для iPhone 3» содержит хорошую главу.

Но мой вопрос заключается в том, если бы мне нужно было программно изменить свои элементы управления (или даже использовать разные представления для каждой ориентации)на земле людям поддерживать свою кодовую базу?Я могу представить столько проблем со спагетти-кодом / тысячами проверок «если» повсюду, что я бы сошел с ума, сделав одно небольшое изменение в структуре пользовательского интерфейса.вопрос?Какой хороший способ контролировать это?

Большое спасибо Марк

Ответы [ 6 ]

41 голосов
/ 12 мая 2010

Я делаю это двумя простыми методами в моем контроллере вида:

- (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 условного.

7 голосов
/ 12 мая 2010

Это действительно зависит от того, что вы выкладываете.

Если вы посмотрите на приложение Apple Settings, вы увидите, что они используют табличные представления для макета с настраиваемыми ячейками для большинства строк. При этом вы можете позволить простому интерфейсу вращаться довольно дешево, просто заполняя ширину ячеек. Это относится даже к таким вещам, как Почта, где в каждой строке есть ячейки для редактирования текста. И таблицы могут быть прозрачными, с видимыми только кнопками или метками, поэтому они не похожи на таблицы.

Вы можете получить много прибыли из autoresizingMask каждого UIView. Если у вас есть один или несколько элементов, которые могут иметь гибкую высоту, то обычно вы можете получить макет интерфейса, который выглядит хорошо в любой ориентации. В зависимости от того, как это выглядит, иногда вы можете просто прикрепить все к вершине.

В редких случаях, если все элементы интерфейса помещаются в квадрат, вы можете просто повернуть их на месте.

Есть два раза, когда вы должны явно обрабатывать изменения ориентации. Один из них - это когда при вращении вид перемещается снизу вверх. Другой случай, когда у вас есть разные изображения для каждой ориентации, например, если вы всегда хотите иметь полную ширину.

Иногда есть способы обойти оба этих варианта. Вы можете использовать растягиваемые изображения или ограничиться одним просмотром в строке. Или вы можете заблокировать ориентацию для определенных видов.

Если вам необходимо изменить макет представлений, существует явный метод layoutSubviews. Вы должны попытаться обработать все ваши условные макеты в этом одном методе. Он вызывается только при изменении границ вида, например, при повороте или если вы освободили место для клавиатуры. Создайте пользовательское представление для каждой иерархии представлений, которая должна реагировать на ротацию, и разметьте подпредставления оттуда.

2 голосов
/ 12 мая 2010

iPhone SDK построен на основе архитектуры MVC, поэтому теоретически, если вы храните всю свою логику (модель) отдельно от вашего пользовательского интерфейса (представления), вам придется беспокоиться об интерфейсе только в одном месте: контроллеры представления , Для них у вас может быть отдельный контроллер вида для каждой ориентации, каждый из которых затем будет загружен с одним if / else, чтобы выбрать, какой контроллер вида загрузить.

То же самое относится и к поддержке iPhone / iPad, где вы можете загрузить другой контроллер представления, который может обрабатывать большие дисплеи.

1 голос
/ 17 ноября 2010
0 голосов
/ 26 ноября 2011

В своем вопросе вы написали:

Я могу представить столько проблем со спагетти-кодом / тысячами проверок "если" повсюду, что я бы сошел с ума, сделав одно небольшое изменение в структуре пользовательского интерфейса.

Один из способов избежать этого - создать иерархию представлений, которая с самого начала разделяет обработку специфичных для iPhone / iPad изменений. Вам нужно только указать, какое представление изначально загружается для каждого устройства. Затем вы создаете viewcontroller, как обычно, но вы также создаете подкласс для viewcontroller, который вы создали. Один подкласс для каждого устройства. Вот где вы можете поместить специальный код устройства, например, управление ориентацией. Как это:

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
}

--- конец цитаты -

Надеюсь, это поможет. Удачи!

0 голосов
/ 26 ноября 2011

Я не могу ручаться за этот код, и, честно говоря, вышеупомянутая willRotateToInterfaceOrientation прекрасно работает. Вот еще один пример с FBDialog.m из Facebook для 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];
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...