keyboard no UIActionSheet não digita nada
Estou me perguntando por que meu teclado do iPhone aberto por um UITextField não digita nada, exceto a tecla Delete e o botão Limpar dentro do próprio campo de texto. O campo de texto é incorporado em um UIActionSheet com este exemplo de código:
// setup UITextField for the UIActionSheet
UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(8.0, 34.0, 304.0, 30.0)];
NSString* startText = [[self.pathName lastPathComponent] stringByDeletingPathExtension];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.backgroundColor = [UIColor whiteColor];
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.text = startText;
textField.delegate = self;
[textField setKeyboardType:UIKeyboardTypeAlphabet];
[textField setKeyboardAppearance:UIKeyboardAppearanceAlert];
// setup UIActionSheet
UIActionSheet* asheet = [[UIActionSheet alloc] initWithTitle: @"Please enter file name\n\n\n"
delegate: self
cancelButtonTitle: @"Cancel"
destructiveButtonTitle: nil
otherButtonTitles: @"OK", nil];
if ([currentView isKindOfClass:[UIToolbar class]])
[asheet showFromToolbar:(UIToolbar*)currentView];
else if ([currentView isKindOfClass:[UITabBar class]])
[asheet showFromTabBar:(UITabBar*)currentView];
else
[asheet showInView:currentView];
[asheet setFrame:CGRectMake(0.0, 60.0, 320.0, 380.0)];
[asheet insertSubview:textField atIndex:0];
[textField becomeFirstResponder];
// memory management
[textField release];
[asheet release];
Posso pressionar a tecla Shift, mas as teclas não mudam para minúsculas, elas sempre estão em maiúsculas. Bem, nunca usei um campo de texto com uma folha de ação ... o que estou fazendo de errado aqui? Os métodos de delegação para a folha de ação e o campo de texto parecem estar presentes conforme necessári
Editar Alterei a associação de exibição da planilha de ação e o tamanho da planilha de ação:
UIWindow* appWindow = [UIApplication sharedApplication].keyWindow;
[asheet showInView:appWindow];
[asheet setFrame:CGRectMake(0.0, 60.0, 320.0, 204.0)];
while (CGRectEqualToRect(asheet.bounds, CGRectZero))
;
// Add the text field to action sheet
[asheet addSubview:textField];
[textField release];
Agora o teclado não se sobrepõe (ou "se sobrepõe") à planilha de ação, a planilha de ação é exibida corretamente abaixo da barra de status e da barra de navegação e o teclado segue abaixo da planilha de ação e vem de baixo para cim
Se apenas textFieldShouldBeginEditing e textFieldDidBeginEditing é chamado dos métodos delegados do campo de texto, nada mais. A tecla Shift muda quando toco nela, a tecla Apagar funciona, todas as outras teclas são exibidas na torneira - mas não são inseridas no campo de texto. Então, o que é isso tudo?
Solução Graças ao SVD me apontando para o fato de que não parece possível incorporar um UITextField em um UIActionSheet. Como eu quero ter um método que retorne uma string de nome de arquivo com uma folha de ação (só porque eu gosto mais da aparência do que um UIAlertView com um campo de texto adicionado), dediquei mais trabalho a ela e finalmente encontrei uma solução funcional. Compartilho aqui porque percebi que muitos de vocês estavam procurando algo semelhante.
Existem dois aspectos principais a serem considerados para que isso funcione:
o campo de texto não deve ser uma subvisão da planilha de ações, pelo menos no momento em que estiver no estado editável
a folha de ação não deve se sobrepor ao teclado
Ok, aqui vem o código. A solução modal funciona com um segundo runloop, para que os métodos delegados para o campo de texto e a folha de ação possam ser manipulados sem retornar ao chamador - tenho certeza de que isso pode ser dividido na abordagem convencional em que você lida com todo o material delegado sua própria classe.
ModalAction.h:
#import <UIKit/UIKit.h>
@interface ModalAction : NSObject
+ (NSString*)ask: (NSString*)question
withTextPrompt: (NSString*)prompt
textPreset: (NSString*)preset
dockToView: (UIView*)toView;
@end
ModalAction.m:
#import "ModalAction.h"
#define TEXT_FIELD_TAG 9999
#define ACTION_SHEET_TAG 8888
@interface ModalActionDelegate : NSObject <UIActionSheetDelegate, UITextFieldDelegate>
{
CFRunLoopRef currentLoop;
NSString* text;
NSUInteger index;
}
@property (assign) NSUInteger index;
@property (retain) NSString* text;
@end
@implementation ModalActionDelegate
@synthesize index;
@synthesize text;
-(id)initWithRunLoop: (CFRunLoopRef)runLoop
{
if (self = [super init])
currentLoop = runLoop;
return self;
}
// Activate keyboard
- (void)acceptInput: (UIActionSheet*)actionSheet
{
UITextField* textField = (UITextField*)[actionSheet viewWithTag:TEXT_FIELD_TAG];
UIWindow* appWindow = [UIApplication sharedApplication].keyWindow;
CGRect frame = textField.frame;
[appWindow insertSubview:textField aboveSubview:actionSheet];
frame.origin.y += 60.0; // move text field to same position as on action sheet
textField.frame = frame;
[textField becomeFirstResponder];
}
- (void)dealloc
{
self.text = nil;
[super dealloc];
}
#pragma mark -
#pragma mark === UIActionSheetDelegate ===
#pragma mark -
// User pressed button. Retrieve results
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"actionSheet clickedButtonAtIndex:%d", buttonIndex);
UIWindow* appWindow = [UIApplication sharedApplication].keyWindow;
UITextField* textField = (UITextField*)[appWindow viewWithTag:TEXT_FIELD_TAG];
if (textField != nil)
self.text = textField.text;
self.index = buttonIndex;
CFRunLoopStop(currentLoop);
}
#pragma mark -
#pragma mark === UITextFieldDelegate ===
#pragma mark -
- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField
{
NSLog(@"textFieldShouldBeginEditing");
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField*)textField
{
NSLog(@"textFieldDidBeginEditing");
[textField becomeFirstResponder];
}
- (BOOL)textFieldShouldEndEditing:(UITextField*)textField
{
NSLog(@"textFieldShouldEndEditing");
return YES;
}
- (void)textFieldDidEndEditing:(UITextField*)textField
{
NSLog(@"textFieldDidEndEditing");
[textField resignFirstResponder];
}
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string
{
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField*)textField
{
NSLog(@"textFieldShouldClearEditing");
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
NSLog(@"textFieldShouldReturn (%@)", textField.text);
BOOL hasSomeText = ![textField.text isEqualToString:@""];
if (hasSomeText)
{
// send an OK to the action sheet
UIWindow* appWindow = [UIApplication sharedApplication].keyWindow;
UIActionSheet* actionSheet = (UIActionSheet*)[appWindow viewWithTag:ACTION_SHEET_TAG];
if (actionSheet != nil)
{
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
self.text = textField.text;
self.index = 0;
CFRunLoopStop(currentLoop);
[textField resignFirstResponder];
}
}
return hasSomeText;
}
@end
@implementation ModalAction
+ (NSString*)textQueryWith: (NSString*)question
prompt: (NSString*)prompt
textPreset: (NSString*)preset
button1: (NSString*)button1
button2: (NSString*)button2
forView: (UIView*)toView
{
// Create action sheet
CFRunLoopRef currentLoop = CFRunLoopGetCurrent();
ModalActionDelegate* madelegate = [[ModalActionDelegate alloc] initWithRunLoop:currentLoop];
NSString* sheetTitle = [question stringByAppendingString:@"\n\n\n"];
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle: sheetTitle
delegate: madelegate
cancelButtonTitle: button1
destructiveButtonTitle: nil
otherButtonTitles: button2, nil];
actionSheet.tag = ACTION_SHEET_TAG;
// Build text field
UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(8.0, 34.0, 304.0, 30.0)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.tag = TEXT_FIELD_TAG;
textField.placeholder = prompt;
textField.text = preset;
textField.delegate = madelegate;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.keyboardType = UIKeyboardTypeAlphabet;
textField.keyboardAppearance = UIKeyboardAppearanceAlert;
textField.autocapitalizationType = UITextAutocapitalizationTypeWords;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.returnKeyType = UIReturnKeyDone;
// Show action sheet and wait for it to finish displaying
UIWindow* appWindow = [UIApplication sharedApplication].keyWindow;
[actionSheet showInView:appWindow];
[actionSheet setFrame:CGRectMake(0.0, 60.0, 320.0, 204.0)];
while (CGRectEqualToRect(actionSheet.bounds, CGRectZero))
;
// Add the text field to action sheet
[actionSheet addSubview:textField];
[textField release];
// Set the field to first responder and move it into place
[madelegate performSelector: @selector(acceptInput:) withObject: actionSheet];
// Start the run loop
CFRunLoopRun();
// Retrieve the user choices
NSUInteger index = madelegate.index;
NSString* answer = [[madelegate.text copy] autorelease];
if (index == 1)
answer = nil; // assumes cancel in position 1
[textField resignFirstResponder];
[actionSheet release];
textField.delegate = nil;
[textField removeFromSuperview];
[madelegate release];
return answer;
}
+ (NSString*)ask: (NSString*)question
withTextPrompt: (NSString*)prompt
textPreset: (NSString*)preset
dockToView: (UIView*)toView
{
return [ModalAction textQueryWith: question
prompt: prompt
textPreset: preset
button1: NSLocalizedString(@"AlertBtnCancel", @"")
button2: @"OK"
forView: toView];
}
@end
Está sendo executado no Simulator iOS 4.2 e no iOS 4.0.2 de dispositivos reais - espero que também seja útil para outro