【问题标题】:UIAlert partially hidden on iPad horizontal orientation. How to move it up?UIAlert 在 iPad 水平方向上部分隐藏。如何向上移动?
【发布时间】:2010-09-03 10:28:56
【问题描述】:

在我的 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;
}

感谢 Bittu 提供有效的解决方案。这是我对他的想法的实施。我将代码以将警报向上移动到我的子类的新方法中:

- (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]; 
}

【问题讨论】:

    标签: cocoa-touch uitextfield uialertview ipad loginview


    【解决方案1】:

    我在使用 UITextField 作为子视图的 alertView 上遇到了完全相同的问题。我没有采用转换路径,而是采用了一些不同的方法。以下是我的做法。

    首先创建带有文本字段的警报视图:

    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];
        }
    
    }
    

    此方法在“轮换完成”通知发布后发生。因此,在向上滑动的动画开始之前,您会在键盘下方看到部分警报视图。希望这对您的登录警报视图有所帮助。

    【讨论】:

    • 还有一个补充:实现以下 uialertview 委托方法 - (void)didPresentAlertView:(UIAlertView *)alertView;并且在此方法中,执行与 didRotateFromInterfaceOrientation 中相同的检查。如果您在 uiviewcontroller 的当前 interfaceOrietion 已经是横向时显示警报,这将允许修复警报问题。
    • 是的,我马上就看到了。不幸的是,它不起作用,因为在这种情况下,我已经看到警报被系统动画到屏幕的中心,并且不知何故你的代码永远不会运行,就好像它被系统动画抢占了一样。解决方法是延迟你的代码:我在预定 0.25 秒后的 NSTimer 内运行它。
    • 另外我讨厌一件事:你需要通过向客户端控制器添加实现代码来打破封装。我讨厌这样,但我看不到解决办法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多