Włącz kopiowanie i wklejanie na UITextField bez edytowalności
Chcę, aby tekst w UITextField
(lub najlepiej UILabel
) był nieedytowalny , ale jednocześnie dać użytkownikowi możliwość skopiowania go do wklejenia gdzie indziej.
6 answers
Moje ostateczne rozwiązanie było następujące:
Utworzyłem podklasę UILabel (UITextField powinno działać tak samo), która wyświetla Kontroler UIMenuController po naciśnięciu przycisku. CopyableLabel.m wygląda tak:
@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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-30 14:35:55
To pytanie jest dość stare i dziwię się, że nikt nie opublikował rozwiązania bez podklasowania. Pomysł przedstawiony w odpowiedzi @mrueg jest poprawny, ale nie trzeba niczego podklasować. Po prostu natknąłem się na ten problem i rozwiązałem go w ten sposób:
In my view controller:
- (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;
}
Jeśli chcesz, aby to działało dla UILabel
, powinno działać w ten sam sposób, po prostu dodając rozpoznawanie gestów stukania zamiast używać metody delegate.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-02 20:20:00
To zrobi wszystko, czego potrzebujesz. Będzie można skopiować. Ale nie można edytować i nie pokazuje klawiatury ani kursora.
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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 17:10:23
Spróbuj zamiast tego UITextView
(podejrzewam, że to zadziała jak {[1] } dla Ciebie). Testowałem to z jego właściwością editable
ustawioną na NO
i podwójne stukanie w Kopiowanie działało dla mnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-17 10:49:05
Innym rozwiązaniem jest utrzymanie UITextField
włączone, ale programowo uniemożliwia jego edycję. Odbywa się to za pomocą następującej metody delegata:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
return NO;
}
Nie jestem jednak świadomy możliwych ograniczeń, obecnie odpowiada moim potrzebom.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-18 13:18:40
Poniższy kod mnie uratował.
textField.addTarget(target, action: "textFieldEditingDidEndAction:", forControlEvents: [.EditingDidEnd])
Wydaje się, że Paste
jest pojedynczym i kompletnym wydarzeniem edycji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-17 09:19:51