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

Отправка неверных оценок в ландшафтном режиме

У меня проблема с ландшафтным режимом в приложении iPad.

Я создал очень маленький новый проект, чтобы показать свою проблему Я установил UIInterfaceOrientation в pList для UIInterfaceOrientationLandscapeRight

В делегате приложения

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [self.window makeKeyAndVisible];
    MyController *myController = [[MyController alloc] init];
    [self.window addSubview:myController.view];

    return YES;
}

В MyController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"Bounds Height:%f %f", self.view.bounds.size.height, self.view.bounds.size.width);
}

Я также попытался поместить это в viewDidLoad с одинаковыми результатами

Если я запускаю приложение, удерживая устройство в альбомной ориентации, NSLog выводит

Bounds Height: 1004.000000 Bounds Width: 768.000000

Что мне нужно сделать, чтобы получить правильные результаты? Я новичок в этом программировании на iOS, все, что я пытаюсь сделать, это привязать UISlider к нижней части экрана, но когда я получаю неправильные координаты, я не уверен, как это сделать.

4b9b3361

Ответ 1

Я не думаю, что на исходный вопрос был дан ответ, потому что Im испытывает ту же проблему.

Ключ здесь состоит в том, что если симулятор/устройство находится в ландшафтном режиме, а затем вы запускаете свою программу, self.view(frame или bounds) извлекает высоту и ширину портрета. Если ваша программа уже запущена, а затем вы поворачиваете, она дает правильное значение. Это происходит только тогда, когда устройство запускается в Landscape и не поворачивается.

Кто-нибудь еще нашел решение или знает, что я делаю неправильно? Пожалуйста, спасибо.

Возможное решение

Я ранее вызывал свой метод из метода viewDidLoad. Оказывается, этот вид все еще переходил. Мне повезло, вызывая мою функцию из viewDidAppear, которая вызывается после того, как все сделано.

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

Ответ 2

Вы слишком быстро проверяете размер кадра и границ.

Вместо этого проверьте их после вращения:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    NSLog(@"Bounds %@", NSStringFromCGRect(self.view.bounds));
    NSLog(@"Frame %@", NSStringFromCGRect(self.view.frame));
}

(Обратите внимание на мое использование NSStringFromCGRect - удобно!)

Это приводит к выходу:

Bounds {{0, 0}, {1024, 748}}
Frame {{0, 0}, {748, 1024}}

Итак, в этом выпуске фрейм "неправильный", но границы - это то, что вы ожидаете. На самом деле, кадр на самом деле не так, как раз то, как выполняются вычисления рамки → . Поэтому вам нужно получить доступ к границам.

См. также возможно Имею ли я правильное понимание фреймов и границ в UIKit?

N.B. viewDidAppear получает вызов раньше, чем вы думаете по схеме вещей. Согласно документам Apple: "viewDidAppear уведомляет контроллер вида, что его представление было добавлено в окно". Другими словами, это может произойти до того, как будет применено любое вращение.

Ответ 3

У меня была такая же проблема и взломал ее так:

- (CGSize)getRotatedViewSize
{
    BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);

    float max = MAX(self.view.bounds.size.width, self.view.bounds.size.height);
    float min = MIN(self.view.bounds.size.width, self.view.bounds.size.height);

    return (isPortrait ? 
            CGSizeMake(min, max) : 
            CGSizeMake(max, min));            
}

Ответ 4

viewWillAppear (согласно лекциям Павла Хегарти CS193p) предназначен для инициализаций, связанных с геометрией. Поскольку viewDidAppear следует viewWillAppear, имеет смысл, что границы здесь также правильны. Границы представлений еще не установлены в viewDidLoad.

Ответ 5

Помимо viewDidAppear: используйте _window.rootViewController вместо [_window addSubview:_rootViewController.view]. Это также решило мои проблемы на iOS6.

AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
  _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  _rootViewController = [[MyRootViewController alloc] init];
  _window.rootViewController = _rootViewController;
  [_window makeKeyAndVisible];
  return YES;
}

MyRootViewController.m:

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  NSLog(@"bounds: %@", NSStringFromCGRect(self.view.bounds));
  UIView *myView = [[UIView alloc] initWithFrame:self.view.bounds];
  [self.view addSubview:myView];
}

Ответ 6

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

Я продолжал копать немного, и я узнал, что границы также правильны в методе viewWillLayoutSubviews. Поэтому я предполагаю, что наиболее "правильным" способом компоновки ваших представлений в проекте было бы:

  • назначьте и создайте их на viewDidLoad или loadView с фреймами, которые, по вашему мнению, будут исправлены к тому времени.

  • переформатируйте созданные вами представления в viewWillLayoutSubviews, чтобы они находились в правильном положении, когда вид действительно отображается.

Ответ 7

Один из комментариев к принятому ответу содержал решение проблемы для меня.

Существует метод, который вы можете переопределить на UIViewController, называемый viewDidLayoutSubviews, я применил его и скорректировал мои содержащие представления.

И так как его вызываемый после "viewWillAppear" и до "viewDidAppear" изменения, внесенные вами в подзаголовки, отображаются как ожидалось, никаких сбоев.

Ответ 8

У меня случилось то же самое со мной.

Вам нужно поманить iOS и поместить здесь эту строку кода, иначе она даст неверный ответ.

-(void) viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  //required because device orientation will give you the wrong values
  [UIViewController attemptRotationToDeviceOrientation];
  int orientation = [[UIDevice currentDevice] orientation];
  BOOL isPortrait = false;

  if (orientation == 3 || orientation == 4)
    isPortrait = false;
  else
    isPortrait = true;
  NSLog(@"is portrait %i ?", isPortrait);
}

Ответ 9

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect r = self.view.frame;
CGFloat width = r.size.width;
CGFloat height = r.size.height;
r.size.height = (UIInterfaceOrientationIsLandscape(orientation)) ? MIN(width, height): MAX(width, height);
r.size.width  = (UIInterfaceOrientationIsLandscape(orientation)) ? MAX(width, height): MIN(width, height);
self.view.frame = r;