【发布时间】: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