在 UITextField 上启用复制和粘贴而不使其可编辑

Posted

技术标签:

【中文标题】在 UITextField 上启用复制和粘贴而不使其可编辑【英文标题】:Enable copy and paste on UITextField without making it editable 【发布时间】:2009-12-17 09:40:35 【问题描述】:

我希望UITextField(或者理想情况下是UILabel)中的文本不可编辑,但同时让用户能够将其复制并粘贴到其他地方.

【问题讨论】:

【参考方案1】:

我的最终解决方案如下:

我创建了一个 UILabel 的子类(UITextField 应该工作相同),它在被点击后显示一个 UIMenuController。 CopyableLabel.m 看起来像这样:

@implementation CopyableLabel


- (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
if(action == @selector(copy:)) 
    return YES;

else 
    return [super canPerformAction:action withSender:sender];




- (BOOL)canBecomeFirstResponder 
return YES;



- (BOOL)becomeFirstResponder 
if([super becomeFirstResponder]) 
    self.highlighted = YES;
    return YES;

return NO;



- (void)copy:(id)sender 
UIPasteboard *board = [UIPasteboard generalPasteboard];
[board setString:self.text];
self.highlighted = NO;
[self resignFirstResponder];



- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
if([self isFirstResponder]) 
    self.highlighted = NO;
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setMenuVisible:NO animated:YES];
    [menu update];
    [self resignFirstResponder];

else if([self becomeFirstResponder]) 
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:self.bounds inView:self];
    [menu setMenuVisible:YES animated:YES];




@end

【讨论】:

此方法在 tableViewController 中使用时似乎不起作用,但如果您在视图中添加此方法并加载 UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self.yourCopyableLabel action:@selector(tapDetected)]; [self.view addGestureRecognizer:tgr]; 然后将 copyableLabel 实现中的 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 更改为 @,则可以使其工作987654324@ 它应该可以工作 如果可以的话,还可以将UITapGestureRecogniser 添加到特定的单元格中,如果您点击屏幕上任何不可点击的项目,我上面提到的方式会弹出菜单【参考方案2】:

这个问题已经很老了,我很惊讶没有人发布没有子类化的解决方案。 @mrueg 的答案中提出的想法是正确的,但您不需要对任何东西进行子类化。我刚刚遇到这个问题并像这样解决它:

在我的视图控制器中:

- (void)viewDidLoad 
    self.textField.delegate = self;
    self.textField.text = @"Copyable, non-editable string.";


- (BOOL)canBecomeFirstResponder 
    return YES;


- (void)copyTextFieldContent:(id)sender 
    UIPasteboard* pb = [UIPasteboard generalPasteboard];
    pb.string = self.textField.text;


- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 
    // UIKit changes the first responder after this method, so we need to show the copy menu after this method returns.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3*NSEC_PER_SEC)), dispatch_get_main_queue(), ^
         [self becomeFirstResponder];
         UIMenuController* menuController = [UIMenuController sharedMenuController];
         UIMenuItem* copyItem = [[UIMenuItem alloc] initWithTitle:@"Copy"
                                                           action:@selector(copyTextFieldContent:)];
         menuController.menuItems = @[copyItem];
         CGRect selectionRect = textField.frame;
         [menuController setTargetRect:selectionRect inView:self.view];
         [menuController setMenuVisible:YES animated:YES];
     );
     return NO;

如果您想为UILabel 进行这项工作,它应该以相同的方式工作,只需添加一个轻击手势识别器而不是使用委托方法。

【讨论】:

【参考方案3】:

这将满足您的所有需求。将是可复制的。但不可编辑,不会显示键盘或光标。

class ViewController: UIViewController 

    @IBOutlet weak var copyableUneditableTextfield: UITextField!

    override func viewDidLoad() 
        super.viewDidLoad()

        copyableUneditableTextfield.delegate = self
        copyableUneditableTextfield.inputView = UIView()   //prevents keyboard     
        copyableUneditableTextfield.tintColor = .clear     //prevents cursor
        copyableUneditableTextfield.text = "Some Text You Want User To Copy But Not Edit"

    



extension ViewController: UITextFieldDelegate 

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 
        return false //prevents editing
    


【讨论】:

即使尝试了您的代码,我仍然可以编辑文本字段 @palebone 抱歉,我忘了指出您需要让 ViewController 成为 copyableUneditableTextfield 的委托。我已经更新了代码,添加了那行。 我想我试过了,使用 uitexview 并使其可交互但不可编辑要容易得多 如果您只希望文本是可复制的并且不关心它是否被更改,因为外部键盘仍然可以在该字段中键入,这似乎工作正常。这可以通过实现更多的委托方法来解决,或者这种行为是可以接受的,然后委托可以设置为 nil 并且用户将根据需要获得选择/复制,但也将获得粘贴和外部键盘输入。【参考方案4】:

改用UITextView(我怀疑它对你来说就像UILabel)。我将其editable 属性设置为NO 对此进行了测试,双击复制对我有用。

【讨论】:

我怀疑虽然该字段不可编辑,但不会出现粘贴按钮。让我们知道这是否属实。 原来的问题写的不是很清楚。我读到“复制和粘贴的能力”是指将其粘贴到其他地方。以另一种方式阅读它,你怎么可能将一些东西粘贴到一个 not 可编辑的 UI 小部件中?我认为不存在这样的小部件。【参考方案5】:

另一种解决方案是保持UITextField 处于启用状态,但以编程方式阻止它被编辑。这是通过以下委托方法完成的:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

    return NO;

我不知道可能的限制,目前适合我的需要。

【讨论】:

【参考方案6】:

下面的代码救了我。

textField.addTarget(target, action: "textFieldEditingDidEndAction:", forControlEvents: [.EditingDidEnd])

看来Paste 是一个单一且完整的编辑事件。

【讨论】:

以上是关于在 UITextField 上启用复制和粘贴而不使其可编辑的主要内容,如果未能解决你的问题,请参考以下文章

如何控制 UITextField 的复制和粘贴弹出位置?

text 在网页上启用右键单击和复制粘贴

UITextField如何禁用粘贴? [复制]

在 html5 日期字段上启用复制/粘贴

禁用复制,在 UITextfield 中粘贴在 iOS 9.x 中不起作用

WPF 在列表框中启用突出显示、复制和粘贴