UIAlert частично скрыт на iPad горизонтальной ориентации.Как продвинуть это? - PullRequest
0 голосов
/ 03 сентября 2010

В моем приложении для iPad есть окно входа в систему как подкласс UIAlertView, которое добавляет два UITextField с использованием идиомы, найденной в сети.

Проблема в том, что в горизонтальной ориентации предупреждение частично скрыто клавиатурой. А именно кнопки скрыты. Конечно, можно скрыть клавиатуру, чтобы открыть кнопку, но это ужасно.

Способ, которым должна исправить идиома, это добавить преобразование перевода в представление:

CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 100.0); 
[self setTransform:translate];

Однако на самом деле это не работает:

  • в исходной вертикальной ориентации, которая работает (но перестает работать после любого вращения устройства)
  • в исходной горизонтальной ориентации можно увидеть, как оно работает, но предупреждение сразу же возвращается к центру экрана, где оно снова частично скрыто.
  • в любой ориентации после вращения iPad он вообще не работает: ничего не происходит, как будто преобразования даже не было.

(кроме того, эта идея преобразования может перестать {работать | быть необходимой} для iOS 4.x. Но это другая проблема).

Любая идея приветствуется.

Для полноты, вот полный код:

- (id)initWithLogin:(NSString *)defaultLogin delegate:(id)delegate
{
    if (self = [super initWithTitle:@"Username and password"
                            message:@"\n\n\n"
                           delegate:delegate
                  cancelButtonTitle:@"Cancel"
                  otherButtonTitles:@"Enter", nil])
    {
        UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)]; 
        [theTextField setBackgroundColor:[UIColor whiteColor]];
        theTextField.text = defaultLogin;
        theTextField.placeholder = @"username";
        [self addSubview:theTextField];
        self.loginField = theTextField;
        [theTextField release];

        theTextField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 80.0, 260.0, 25.0)]; 
        [theTextField setBackgroundColor:[UIColor whiteColor]]; 
        theTextField.placeholder = @"password";
        theTextField.secureTextEntry = YES;
        [self addSubview:theTextField];
        self.passwordField = theTextField;
        [theTextField release];

    // the two next lines may not be useful for iOS > 4.0
        CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 100.0); 
        [self setTransform:translate];
    }
    return self;
}

Спасибо за Битту за рабочее решение. Вот моя реализация его идеи. Я поместил код для перемещения оповещения в новый метод моего подкласса:

- (void)slideUp
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    [UIView beginAnimations:nil context:context];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.25f];           

    CGPoint center = self.center;
    center.y -= 100;
    self.center = center;

    [UIView commitAnimations];
}

Ключевой момент - когда вызывать этот код. Есть два случая: самый простой случай, когда пользователь поворачивает устройство. К сожалению, класс Alert не проинформирован об этом событии, только клиентский UIViewController, поэтому нам нужно было его вызвать. Это уродливо, нарушая инкапсуляцию, но пусть будет так:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{
    if(loginWindow && UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
    {
        [loginWindow slideUp];
    }   
}

Второй случай, когда при открытии оповещения ориентация уже горизонтальная. Делегат оповещения информируется об этом в своем методе делегата didPresentAlertView:.

- (void)didPresentAlertView:(UIAlertView *)alertView
{
    if ( UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ) {
        [self slideUp];
    }
}

К сожалению, эта реализация не работает, потому что вызов slideUp в это время будет конфликтовать с системой, уже анимирующей предупреждение к центру экрана. Решение состоит в том, чтобы немного задержать вызов, например, используя NSTimer:

- (void)didPresentAlertView:(UIAlertView *)alertView
{
    if ( UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ) {
        [NSTimer scheduledTimerWithTimeInterval:0.25f
                                      target:self
                                    selector:@selector(slideUp)
                                    userInfo:nil
                                     repeats:NO];
    }
}

Кстати, slideUp не имеет документированной подписи для селектора NSTimer, но, похоже, все еще работает! Если это вас беспокоит, просто добавьте промежуточный метод с правильной подписью:

- (void)slideUpByTimer:(NSTimer*)theTimer
{
    [self slideUp]; 
}

1 Ответ

1 голос
/ 03 сентября 2010

У меня была такая же проблема с alertView с UITextField в качестве подпредставления. Вместо пути преобразования я выбрал немного другой подход. Вот как я это сделал.

Сначала создайте представление оповещения с текстовым полем в нем:

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 40.0, 260.0, 25.0)];
[textField setBackgroundColor:[UIColor whiteColor]];
textField.placeholder = @"Search";

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Enter Search Text" message:@"        " delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Enter",nil];

[alertView addSubview:textField];
[alertView show];

Затем в UIViewController, который будет отображать представление предупреждений, реализуйте этот метод:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{

    if(self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft || self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
    {
         CGContextRef context = UIGraphicsGetCurrentContext();
         [UIView beginAnimations:nil context:context];
         [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
         [UIView setAnimationDuration:0.25f];           

         CGPoint center = self.alertView.center;
         center.y -= 100;
         self.alertView.center = center;

         [UIView commitAnimations];
    }

}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...