UIActionSheet中的键盘没有输入任何内容

时间:2011-04-08 01:29:26

标签: iphone keyboard uitextfield uiactionsheet

我想知道为什么我的UITextField打开的iPhone键盘除了删除键和文本字段内的清除按钮之外没有输入任何内容。文本字段嵌入在UIActionSheet中,其中包含以下代码示例:

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

我可以按下shift键,但键不会改为小写,它们总是大写的。好吧,我从未使用过带有操作表的文本字段......我在这里做错了什么?行动表和文本字段的委托方法似乎根据需要存在。

修改 我已经更改了操作表的视图关联和操作表的大小:

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

现在键盘没有被操作表重叠(或“重叠不足”),操作表正确显示在状态栏和导航栏下方,键盘位于操作表下方,自下而上。

但只有 textFieldShouldBeginEditing textFieldDidBeginEditing 才能调用文本字段的委托方法,仅此而已。当我点击它时,Shift键会改变,擦除键可以工作,所有其他键都可以自动显示 - 但不要插入文本字段。那么,它到底是什么?

解决方案: 感谢SVD指出我似乎不可能将UITextField嵌入到UIActionSheet中。因为我想要一个方法来返回带有操作表的文件名字符串(因为我喜欢外观而不是添加了文本字段的UIAlertView)我已经花了更多的工作并最终找到了一个有效的解决方案。我在这里分享,因为我意识到你们中有很多人在寻找类似的东西。

要使这项工作有两个主要方面需要考虑:

  • 文本字段不能是操作表的子视图,至少在 它处于可编辑状态的时刻

  • 操作表不应与键盘重叠

好的,代码来了。模态解决方案适用于第二个runloop,因此可以处理文本字段和操作表的委托方法,无需返回调用者 - 我确信这可以分解为传统方法,您可以在其中处理所有委托内容你自己的班级。

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

它在模拟器iOS 4.2和真实设备的iOS 4.0.2上运行 - 我希望它对其他人也有帮助。

1 个答案:

答案 0 :(得分:2)

关于操作表的一个奇怪之处在于,例如,如果存在标签栏,标签栏可能会“窃取”某些操作表单击,即使可视化操作表位于顶部。

您的操作表高度为380像素 - 因此当键盘滑出时,它会与操作表重叠。也许在这种情况下,是操作表窃取键盘的水龙头?尝试使操作表更小,更靠近顶部 - 例如为了测试这个想法,我只是让它起源于0,0和240像素高。

编辑:

显然这是一个问题 - 它对我来说不适用于简单的测试应用程序,没有标签栏或工具栏。我发现了这些链接:

使用警报视图执行此操作似乎有效(尽管它似乎只适用于警报视图): http://discussions.info.apple.com/thread.jspa?threadID=1674641&start=0&tstart=0

而这里有人制作了自己的“行动表”: how to enable text input in UITextField which is in UIActionSheet?