Подтвердить что ты не робот

Управление ориентацией iphone/ipad

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

Я просмотрел большое количество doco, и моя книга "Начало разработки iPhone 3" имеет приятную главу.

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

Есть ли у кого-нибудь опыт в решении этой проблемы? Какой хороший способ контролировать это?

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

4b9b3361

Ответ 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);
        ...
    }
}

Чтобы сохранить эту чистоту, вы можете легко разделить настройки/перезагрузку/etc. с методами, вызванными изнутри одиночного if-else условного.

Ответ 2

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

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

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

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

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

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

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

Ответ 3

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

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

Ответ 5

Я не могу ручаться за этот код, и, честно говоря, вышеупомянутое 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 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

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

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

Один из способов уклониться от этого заключается в том, чтобы создать иерархию представлений, которая с самого начала разделяет обработку конкретных изменений iPhone/iPad. Вам нужно было только установить, какой вид изначально загружен для каждого устройства. Затем вы создаете 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
}

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

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