Chức UITextView
năng Sao chép, Cắt, Chọn, Chọn Tất cả được hiển thị theo mặc định khi tôi nhấn xuống trên màn hình. Nhưng, trong dự án của tôi UITextField
là chỉ đọc. Tôi không yêu cầu chức năng này. Vui lòng cho tôi biết cách tắt tính năng này.
Chức UITextView
năng Sao chép, Cắt, Chọn, Chọn Tất cả được hiển thị theo mặc định khi tôi nhấn xuống trên màn hình. Nhưng, trong dự án của tôi UITextField
là chỉ đọc. Tôi không yêu cầu chức năng này. Vui lòng cho tôi biết cách tắt tính năng này.
Câu trả lời:
Cách dễ nhất để vô hiệu hóa các hoạt động của bảng dán là tạo một lớp con của lớp UITextView
đó ghi đè canPerformAction:withSender:
phương thức để trả về NO
các hành động mà bạn không muốn cho phép:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(paste:))
return NO;
return [super canPerformAction:action withSender:sender];
}
Cũng xem UIResponder
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; }
- để chặn tất cả các tùy chọn
Lớp con UITextView và ghi đè lên canBecomeFirstResponder:
- (BOOL)canBecomeFirstResponder {
return NO;
}
Lưu ý rằng điều này chỉ áp dụng cho UITextViews không thể chỉnh sửa! Chưa thử nghiệm nó trên những cái có thể chỉnh sửa ...
return NO;
về - (BOOL)canPerformAction:(SEL)action withSender:(id)sender
phương pháp là một lựa chọn tốt hơn.
Nếu bạn muốn tắt tính năng cắt / sao chép / dán trên tất cả UITextView
ứng dụng của mình, bạn có thể sử dụng một danh mục với:
@implementation UITextView (DisableCopyPaste)
- (BOOL)canBecomeFirstResponder
{
return NO;
}
@end
Nó lưu một lớp con ... :-)
UITextView
hoạt động như mong đợi, chẳng hạn như khi nó có thể chỉnh sửa và nhận được liên lạc. Nó là nhiều để ghi đè canPerformAction:withSender:
; đó là những gì giao thức dành cho.
Đây là giải pháp làm việc tốt nhất cho tôi:
UIView *overlay = [[UIView alloc] init];
[overlay setFrame:CGRectMake(0, 0, myTextView.contentSize.width, myTextView.contentSize.height)];
[myTextView addSubview:overlay];
[overlay release];
@rpetrich câu trả lời phù hợp với tôi. Tôi đang đăng mã mở rộng để phòng trường hợp ai đó tiết kiệm thời gian.
Trong trường hợp của tôi, tôi không muốn bất kỳ cửa sổ bật lên nào, nhưng tôi muốn UITextField có thể trở thành người phản hồi đầu tiên.
Thật không may, bạn vẫn nhận được cửa sổ bật lên của kính lúp khi bạn chạm và giữ trường văn bản.
@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
Swift 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)
}
}
Nếu bạn không cần UITextView để cuộn, thì giải pháp đơn giản nhất không liên quan đến phân loại phụ là chỉ cần tắt tương tác của người dùng đối với chế độ xem văn bản:
textField.userInteractionEnabled = NO;
Cách dễ nhất là tạo một lớp con của UITextView ghi đè 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;
}
Khi tôi trả về NO trong canPerformAction trên iOS 7, tôi sẽ gặp rất nhiều lỗi như sau:
<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.
Giải pháp của tôi là như sau:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
}];
return [super canPerformAction:action withSender:sender];
}
Bí quyết là ẩn bộ điều khiển menu trong chu kỳ tiếp theo trên hàng đợi chính (ngay sau khi nó được hiển thị).
Đây là cách dễ nhất để tắt toàn bộ Menu Chọn / Sao chép / Dán trong UITextView
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[UIMenuController sharedMenuController].menuVisible = NO;
return NO;
}
Nếu bạn đang tìm cách thay thế bàn phím bằng một, giả sử UIPicker
như là inputView
(tất nhiên là một thanh công cụ inputAccesotyView
), thì giải pháp này có thể giúp ...
textFieldShouldBeginEditing:
textField.userInteractionEnabled = NO;
UIPickerView
, hãy đặt nó thành CÓ.Bằng cách làm này, bạn có thể nhấn vào UITextField
và hiển thị các tùy chọn để lựa chọn UIPickerView
, tại thời điểm này, bạn UITextField
sẽ thực sự không phản ứng với bất kỳ sự kiện chạm nào (điều này bao gồm chạm và giữ để cắt, sao chép và dán). Tuy nhiên, bạn sẽ phải nhớ đặt nó trở lại CÓ khi bạn đóng tài khoản của mình, UIPickerView
tuy nhiên bạn sẽ không thể truy cập UIPickerView
lại.
Thời điểm duy nhất khi nó không thành công là khi người dùng bắt đầu bằng cách chạm và giữ UITextView
, sau đó bạn sẽ thấy bản sao cắt và dán lại lần đầu tiên. Đây là lý do tại sao bạn nên luôn xác nhận đầu vào của mình. Đây là cách dễ nhất tôi có thể nghĩ đến. Tùy chọn khác là sử dụng UILabel
cho văn bản chỉ đọc nhưng bạn bỏ lỡ rất nhiều chức năng tuyệt vời từ đó UITextView
.
Nếu bạn muốn tắt cửa sổ bật lên UITextField
thì hãy thử UITextFieldDelegate
phương pháp này để chuyển đổi isUserInteractionEnabled
.
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = false
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = true
return true
}
Tôi đã cung cấp một câu trả lời có hiệu quả ở đây để tắt tính năng chọn văn bản + kính lúp, giữ các liên kết có thể kéo được bật Hy vọng điều đó sẽ giúp:
Sau một thời gian dài cố gắng, tôi đã cố gắng dừng việc chọn văn bản, phóng to và giữ phát hiện dữ liệu (liên kết có thể nhấp, v.v.) bằng cách ghi đè addGestureRecognizer trên một lớp con UITextView chỉ cho phép UILongPressGestureRecognizer trì hoãn kết thúc chạm:
UIUnselectableTextView.m
-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && gestureRecognizer.delaysTouchesEnded)
{
[super addGestureRecognizer:gestureRecognizer];
}
}
Đối với Swift 3, nó được thay đổi thành:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
Tôi đã làm xong rồi. Trên của tôi, UITextView
tôi đã tắt tùy chọn cắt, sao chép, chọn, v.v. rất dễ dàng.
Tôi đã đặt một UIView
ở cùng một nơi mà tôi đã đặt UITextView
, nhưng trên self.view
và thêm một touchDelegate
phương thức như sau:
(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;
}
}
}
và nó đã làm việc cho tôi. Cảm ơn bạn.
Nhanh
textView.selectable = false // disable text selection (and thus copy/paste/etc)
Có liên quan
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.
Nếu bạn muốn thêm một tùy chọn tùy chỉnh vào UITextView của mình nhưng vô hiệu hóa các chức năng hiện có thì đây là cách bạn thực hiện trên Swift 3 :
Để tắt tính năng sao chép, dán, cắt tính năng tạo một lớp con và ghi đè lên các lớp sau:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
Trên ViewController, bạn có CustomTextView của mình thêm những thứ sau để thêm các tùy chọn của bạn:
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)")
}
Phương pháp này sẽ vô hiệu hóa hoàn toàn menu Chọn, Chọn tất cả, Dán. Nếu bạn vẫn nhận được một số hành động khác, thì chỉ cần thêm hành động đó vào điều kiện if như bên dưới.
- (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];
}
Bạn chỉ có thể tạo danh mục như thế này:
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
Phân lớp con UITextView
và ghi đè - (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
là một khả năng khác để vô hiệu hóa các hành động không mong muốn.
Sử dụng lớp của gestureRecognizer
-object để quyết định xem có nên thêm hành động hay không.
(SWIFT) Nếu bạn chỉ muốn một trường văn bản cơ bản mà không có tùy chọn menu hoặc kính lúp nào thì hãy tạo một lớp con của UITextField trả về giá trị false cho scrollRecognizerShouldBegin:
class TextFieldBasic: UITextField {
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
Thao tác này sẽ bỏ qua tất cả chức năng cảm ứng trên trường văn bản nhưng vẫn cho phép bạn sử dụng bàn phím bật lên để thêm / xóa ký tự.
Nếu bạn đang sử dụng bảng phân cảnh, chỉ cần gán lớp mới được tạo cho trường văn bản hoặc nếu bạn đang tạo trường văn bản theo chương trình:
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)}
Swift 3
Để làm điều này, bạn cần phân lớp UITextView của mình và đặt phương thức này.
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 có hai thuộc tính sẽ thực hiện những gì bạn cần: isSelectable và isEditable .
Đặt isEditable thành false bạn sẽ tránh được việc người dùng chỉnh sửa văn bản và đặt isSelectable thành false bạn sẽ tránh được việc người dùng chọn văn bản bên trong textView của bạn, vì vậy điều này sẽ ngăn menu hành động được hiển thị.
Vui lòng tìm mã mẫu để tham khảo:
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
}
Sử dụng func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { retrun bool }
thay cho 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
}
}
Tạo một lớp mới với tên StopPasteAction.swift
import UIKit
class StopPasteAction: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
Thêm lớp mới lớp với bạn TextField hiện tại