Funkcje UITextViewKopiuj, Wytnij, Wybierz, Zaznacz wszystko są wyświetlane domyślnie po naciśnięciu ekranu. Ale w moim projekcie UITextFieldjest tylko do odczytu. Nie potrzebuję tej funkcjonalności. Powiedz mi, jak wyłączyć tę funkcję.
Funkcje UITextViewKopiuj, Wytnij, Wybierz, Zaznacz wszystko są wyświetlane domyślnie po naciśnięciu ekranu. Ale w moim projekcie UITextFieldjest tylko do odczytu. Nie potrzebuję tej funkcjonalności. Powiedz mi, jak wyłączyć tę funkcję.
Odpowiedzi:
Najłatwiejszym sposobem wyłączenia operacji wklejania jest utworzenie podklasy, UITextViewktóra przesłania canPerformAction:withSender:metodę zwracania NOdziałań, na które nie chcesz zezwolić:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(paste:))
return NO;
return [super canPerformAction:action withSender:sender];
}
Zobacz także UIResponder
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; }- zablokować wszystkie opcje
Podklasa UITextView i nadpisanie canBecomeFirstResponder:
- (BOOL)canBecomeFirstResponder {
return NO;
}
Zwróć uwagę, że dotyczy to tylko nieedytowalnych UITextViews! Nie testowałem tego na edytowalnych ...
return NO;o - (BOOL)canPerformAction:(SEL)action withSender:(id)sendermetodzie jest lepszym rozwiązaniem.
Jeśli chcesz wyłączyć wycinanie / kopiowanie / wklejanie we wszystkich UITextView swoich aplikacjach, możesz użyć kategorii z:
@implementation UITextView (DisableCopyPaste)
- (BOOL)canBecomeFirstResponder
{
return NO;
}
@end
Zapisuje podklasę ... :-)
UITextViewzachowywaniu się zgodnie z oczekiwaniami, na przykład, gdy można go edytować i można go dotknąć. To dużo do przesłonięcia canPerformAction:withSender:; do tego służy protokół.
To było dla mnie najlepsze działające rozwiązanie:
UIView *overlay = [[UIView alloc] init];
[overlay setFrame:CGRectMake(0, 0, myTextView.contentSize.width, myTextView.contentSize.height)];
[myTextView addSubview:overlay];
[overlay release];
@rpetrich answer zadziałało dla mnie. Wysyłam rozszerzony kod na wypadek, gdyby zaoszczędził komuś trochę czasu.
W moim przypadku nie chcę żadnego wyskakującego okienka, ale chcę, aby UITextField mógł zostać pierwszym respondentem.
Niestety, po dotknięciu i przytrzymaniu pola tekstowego nadal pojawia się wyskakujące okienko lupy.
@interface NoSelectTextField : UITextField
@end
@implementation NoSelectTextField
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(paste:) ||
action == @selector(cut:) ||
action == @selector(copy:) ||
action == @selector(select:) ||
action == @selector(selectAll:) ||
action == @selector(delete:) ||
action == @selector(makeTextWritingDirectionLeftToRight:) ||
action == @selector(makeTextWritingDirectionRightToLeft:) ||
action == @selector(toggleBoldface:) ||
action == @selector(toggleItalics:) ||
action == @selector(toggleUnderline:)
) {
return NO;
}
return [super canPerformAction:action withSender:sender];
}
@end
Szybki 4
class NoSelectTextField: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(paste(_:)) ||
action == #selector(cut(_:)) ||
action == #selector(copy(_:)) ||
action == #selector(select(_:)) ||
action == #selector(selectAll(_:)) ||
action == #selector(delete(_:)) ||
action == #selector(makeTextWritingDirectionLeftToRight(_:)) ||
action == #selector(makeTextWritingDirectionRightToLeft(_:)) ||
action == #selector(toggleBoldface(_:)) ||
action == #selector(toggleItalics(_:)) ||
action == #selector(toggleUnderline(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
Jeśli nie potrzebujesz UITextView do przewijania, najprostszym rozwiązaniem, które nie obejmuje podklas, jest po prostu wyłączenie interakcji użytkownika dla widoku tekstu:
textField.userInteractionEnabled = NO;
Najłatwiejszym sposobem jest utworzenie podklasy UITextView, która przesłania canPerformAction: withSender:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[UIMenuController sharedMenuController].menuVisible = NO; //do not display the menu
[self resignFirstResponder]; //do not allow the user to selected anything
return NO;
}
Kiedy zwrócę NIE w canPerformAction na iOS 7, otrzymam wiele błędów takich jak ten:
<Error>: CGContextSetFillColorWithColor: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
Moje rozwiązanie jest następujące:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
}];
return [super canPerformAction:action withSender:sender];
}
Sztuczka polega na tym, aby w kolejnym cyklu w głównej kolejce ukryć kontroler menu (tuż po jego wyświetleniu).
Jest to najłatwiejszy sposób na wyłączenie całego menu Wybierz / Kopiuj / Wklej w UITextView
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[UIMenuController sharedMenuController].menuVisible = NO;
return NO;
}
Jeśli chcesz zastąpić klawiaturę, powiedzmy, UIPickerjako inputView(oczywiście z paskiem narzędzi jako inputAccesotyView), to obejście może pomóc ...
textFieldShouldBeginEditing:textField.userInteractionEnabled = NO;UIPickerView, ustaw go na TAK.W ten sposób będziesz mógł dotknąć UITextFieldi wyświetlić opcje do wyboru UIPickerView, w tym momencie UITextFieldrzeczywiście nie zareagowałbyś na żadne zdarzenie dotykowe (obejmuje to dotknięcie i przytrzymanie do wycinania, kopiowania i wklejania). Musisz jednak pamiętać, aby ustawić go z powrotem na TAK podczas zamykania konta, UIPickerViewale nie będziesz mieć dostępu do swojegoUIPickerView ponownie.
Jedynym momentem, w którym to się nie powiedzie, jest to, że użytkownik zaczyna od dotknięcia i przytrzymania przycisku UITextView, a następnie po raz pierwszy zobaczysz wycinanie, kopiowanie i wklejanie. Dlatego zawsze należy sprawdzać poprawność wprowadzonych danych. To najłatwiejsza rzecz, jaką przychodzi mi do głowy. Inną opcją było użycie UILabeltekstu tylko do odczytu, ale brakuje Ci wielu wspaniałych funkcji z UITextView.
Jeśli chcesz wyłączyć wyskakujące okienko, UITextFieldwypróbuj tę UITextFieldDelegatemetodę, aby przełączyć isUserInteractionEnabled.
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = false
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = true
return true
}
Podałem tutaj działającą odpowiedź , aby wyłączyć zaznaczanie tekstu + lupę, zachowując włączone klikalne linki. Mam nadzieję, że to pomoże:
Po dość długich próbach udało mi się zatrzymać zaznaczanie tekstu, powiększanie i utrzymywanie wykrywania danych (klikalne linki itp.), Zastępując addGestureRecognizer w podklasie UITextView, pozwalając tylko UILongPressGestureRecognizer opóźniać zakończenie dotyku:
UIUnselectableTextView.m
-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && gestureRecognizer.delaysTouchesEnded)
{
[super addGestureRecognizer:gestureRecognizer];
}
}
W przypadku Swift 3 zmieniono na:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
Zrobiłem to. Na moim UITextViewbardzo łatwo wyłączyłem opcję wycinania, kopiowania, zaznaczania itp.
Umieściłem UIVieww tym samym miejscu, w którym umieściłem UITextView, ale na self.viewi dodałem touchDelegatemetodę w następujący sposób:
(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *scrollTouch=[touches anyObject];
if(scrollTouch.view.tag==1)
{
NSLog(@"viewTouched");
if(scrollTouch.tapCount==1)
[textView1 becomeFirstResponder];
else if(scrollTouch.tapCount==2)
{
NSLog(@"double touch");
return;
}
}
}
i to zadziałało dla mnie. Dziękuję Ci.
Szybki
textView.selectable = false // disable text selection (and thus copy/paste/etc)
Związane z
textView.editable = false // text cannot be changed but can still be selected and copied
textView.userInteractionEnabled = false // disables all interaction, including scrolling, clicking on links, etc.
Jeśli chcesz dodać niestandardową opcję do swojego UITextView, ale wyłączyć istniejące funkcje, oto jak to zrobić w Swift 3 :
Aby wyłączyć kopiowanie, wklejanie, wycinanie, utwórz podklasę i nadpisz następujące elementy:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
W kontrolerze ViewController masz swój CustomTextView dodaj następujące elementy, aby dodać opcje:
let selectText = UIMenuItem(title: "Select", action: #selector(ViewController.selected))
func selected() {
if let selectedRange = textView.selectedTextRange, let
selectedText = textView.text(in: selectedRange) {
}
print("User selected text: \(selectedText)")
}
Ta metoda całkowicie wyłączy menu Wybierz, Zaznacz wszystko, Wklej. Jeśli nadal otrzymujesz inną akcję, po prostu dodaj ją do warunku if, jak poniżej.
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender // This is to disable select / copy / select all / paste menu
{
if (action == @selector(copy:) || action == @selector(selectAll:) || action == @selector(select:) || action == @selector(paste:))
return NO;
return [super canPerformAction:action withSender:sender];
}
Możesz po prostu utworzyć taką kategorię:
UITextView + Selectable. H
@interface UITextView (Selectable)
@property (nonatomic, assign, getter = isTextSelectable) bool textSelectable;
@end
UITextView + Selectable. M
#import "UITextView+Selectable.h"
#import <objc/runtime.h>
#define TEXT_SELECTABLE_PROPERTY_KEY @"textSelectablePropertyKey"
@implementation UITextView (Selectable)
@dynamic textSelectable;
-(void)setTextSelectable:(bool)textSelectable {
objc_setAssociatedObject(self, TEXT_SELECTABLE_PROPERTY_KEY, [NSNumber numberWithBool:textSelectable], OBJC_ASSOCIATION_ASSIGN);
}
-(bool)isTextSelectable {
return [objc_getAssociatedObject(self, TEXT_SELECTABLE_PROPERTY_KEY) boolValue];
}
-(bool)canBecomeFirstResponder {
return [self isTextSelectable];
}
@end
Podklasy UITextViewi nadpisywanie - (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizerto kolejna możliwość wyłączenia niechcianych działań.
Użyj klasy obiektu gestureRecognizer-object, aby zdecydować, czy akcja powinna zostać dodana, czy nie.
(SWIFT) Jeśli chcesz mieć tylko podstawowe pole tekstowe bez opcji menu ani szkła powiększającego, utwórz podklasę UITextField zwracającą false do gestRecognizerShouldBegin:
class TextFieldBasic: UITextField {
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
Spowoduje to pominięcie wszystkich funkcji dotykowych w polu tekstowym, ale nadal umożliwi używanie wyskakującej klawiatury do dodawania / usuwania znaków.
Jeśli używasz scenorysu, po prostu przypisz nowo utworzoną klasę do pola tekstowego lub jeśli programowo tworzysz pole tekstowe:
var basicTextField = TextFieldBasic()
basic = basicTextField(frame: CGRectMake(10, 100, 100,35))
basic.backgroundColor = UIColor.redColor()
self.view.addSubview(basic)
basic.becomeFirstResponder()
override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool
{
NSOperationQueue .mainQueue().addOperationWithBlock({ () -> Void in
[UIMenuController .sharedMenuController() .setMenuVisible(false, animated: true)]
})
return super.canPerformAction(action, withSender: sender)}
Szybki 3
Aby to zrobić, musisz utworzyć podklasę swojego UITextView i umieścić tę metodę.
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if (action == #selector(copy(_:))) {
return false
}
if (action == #selector(cut(_:))) {
return false
}
if (action == #selector(paste(_:))) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
UITextView ma dwie właściwości, które zrobią to, czego potrzebujesz: isSelectable i isEditable .
Ustawienie isEditable na false pozwoli uniknąć użytkownikowi edycji tekstu, a ustawienie isSelectable na false pozwoli uniknąć użytkownikowi wybierania tekstu w Twoim textView, co zapobiegnie wyświetlaniu menu akcji.
Proszę znaleźć przykładowy kod w celach informacyjnych:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(copy(_:)) || action == #selector(paste(_:)) || action == #selector(UIResponderStandardEditActions.paste(_:)) ||
action == #selector(replace(_:withText:)) ||
action == #selector(UIResponderStandardEditActions.cut(_:)) ||
action == #selector(UIResponderStandardEditActions.select(_:)) ||
action == #selector(UIResponderStandardEditActions.selectAll(_:)) ||
action == #selector(UIResponderStandardEditActions.delete(_:)) ||
action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionLeftToRight(_:)) ||
action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionRightToLeft(_:)) ||
action == #selector(UIResponderStandardEditActions.toggleBoldface(_:)) ||
action == #selector(UIResponderStandardEditActions.toggleItalics(_:)) ||
action == #selector(UIResponderStandardEditActions.toggleUnderline(_:)) ||
action == #selector(UIResponderStandardEditActions.increaseSize(_:)) ||
action == #selector(UIResponderStandardEditActions.decreaseSize(_:))
{
return false
}
return true
}
Użyj func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { retrun bool }zamiast textFieldShouldBeginEditing.
class ViewController: UIViewController , UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//Show date picker
let datePicker = UIDatePicker()
datePicker.datePickerMode = UIDatePickerMode.date
textField.tag = 1
textField.inputView = datePicker
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField.tag == 1 {
textField.text = ""
return false
}
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.tag == 1 {
textField.text = ""
return false
}
return true
}
}
Utwórz nową klasę o nazwie StopPasteAction.swift
import UIKit
class StopPasteAction: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
Dodaj klasę nową klasę z bieżącym TextField