7

電話に付属するメッセージアプリに似たiPhoneアプリを作成しています。UIMenuController を介してメッセージをコピーする機能をセットアップしましたが、キーボードが表示されているときに誰かがメッセージをコピーしようとすると、キーボードが消えます (おそらく、メッセージ セルがコピーされている[cell becomeFirstResponder];場所が原因です)。cell

キーボードを失うことなくコピー メッセージを表示する方法はありますか?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath {

    //...other cell setup stuff...

    UILongPressGestureRecognizer *longPressGesture =
    [[UILongPressGestureRecognizer alloc]
      initWithTarget:self action:@selector(showCopyDialog:)];
    [cell addGestureRecognizer:longPressGesture];

    return cell;
}

- (void)showCopyDialog:(UILongPressGestureRecognizer *)gesture
{
    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        ConvoMessageCell *cell = (ConvoMessageCell *)[gesture view];
        NSIndexPath *indexPath = [self.tblConvo indexPathForCell:cell];

        UIMenuController *theMenu = [UIMenuController sharedMenuController];
        [cell becomeFirstResponder];
        [theMenu setTargetRect:CGRectMake(menuX, menuY, 100, 100) inView:cell];
        [theMenu setMenuVisible:YES animated:YES];        
    }
}
4

2 に答える 2

17

次のように、UITextView をサブクラス化して、nextResponder をオーバーライドし、組み込みアクション (Paste) を無効にする方法を提供することで、このジレンマを解決しました。

@interface CustomResponderTextView : UITextView

@property (nonatomic, weak) UIResponder *overrideNextResponder;

@end

@implementation CustomResponderTextView

@synthesize overrideNextResponder;

- (UIResponder *)nextResponder {
    if (overrideNextResponder != nil)
        return overrideNextResponder;
    else
        return [super nextResponder];
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (overrideNextResponder != nil)
        return NO;
    else
        return [super canPerformAction:action withSender:sender];
}

@end

次に、ジェスチャー アクション ハンドラーで、テキスト ビューが既にファーストレスポンダーであるかどうかを確認します。その場合は、次のレスポンダーをオーバーライドします。それ以外の場合、キーボードはとにかく隠されている可能性があり、簡単にできますbecomeFirstResponder。メニューが非表示になったら、オーバーライドをリセットする必要もあります。

if ([inputView isFirstResponder]) {
    inputView.overrideNextResponder = self;
    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(menuDidHide:)
        name:UIMenuControllerDidHideMenuNotification object:nil];
} else {
    [self becomeFirstResponder];
}

- (void)menuDidHide:(NSNotification*)notification {

    inputView.overrideNextResponder = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self
        name:UIMenuControllerDidHideMenuNotification object:nil];
}

iOS 5 で導入されたテーブル ビュー デリゲート メソッド (shouldShowMenuForRowAtIndexPathなど) を使用することは、メニューの配置を制御する必要があったため、私にとっては解決策ではありませんでした (デフォルトでは、セルの水平方向の中央に単純に配置されていますが、メッセージ バブルとメニューを実際のバブルの中央に配置したかった)。

于 2012-11-10T18:04:12.137 に答える
7

iOS 5 では、テーブル ビューのデリゲート メソッドを使用してメニュー コントローラーを表示できるようになりました。

- (BOOL) tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;

この方法でメニュー コントローラーを表示しても、キーボードは無効になりません。

iOS 5より前のバージョンをサポートするアプリを持っているので、あなたが言っていることもやりたいと思っています(コピーメニューが表示されたときにキーボードを辞任しないでください)。

于 2012-03-02T22:14:19.690 に答える