ฟังก์ชันการUITextView
คัดลอกตัดเลือกเลือกทั้งหมดจะแสดงตามค่าเริ่มต้นเมื่อฉันกดลงบนหน้าจอ แต่ในโครงการของฉันUITextField
เป็นเพียงการอ่านเท่านั้น ฉันไม่ต้องการฟังก์ชันนี้ โปรดบอกวิธีปิดใช้งานคุณลักษณะนี้
ฟังก์ชันการUITextView
คัดลอกตัดเลือกเลือกทั้งหมดจะแสดงตามค่าเริ่มต้นเมื่อฉันกดลงบนหน้าจอ แต่ในโครงการของฉันUITextField
เป็นเพียงการอ่านเท่านั้น ฉันไม่ต้องการฟังก์ชันนี้ โปรดบอกวิธีปิดใช้งานคุณลักษณะนี้
คำตอบ:
วิธีที่ง่ายที่สุดในการปิดใช้งานการดำเนินการวางบอร์ดคือการสร้างคลาสย่อยUITextView
ซึ่งจะแทนที่canPerformAction:withSender:
เมธอดเพื่อส่งคืนNO
การดำเนินการที่คุณไม่ต้องการอนุญาต:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(paste:))
return NO;
return [super canPerformAction:action withSender:sender];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; }
- เพื่อปิดกั้นตัวเลือกทั้งหมด
Subclass UITextView และเขียนทับ canBecomeFirstResponder:
- (BOOL)canBecomeFirstResponder {
return NO;
}
โปรดทราบว่าสิ่งนี้ใช้ได้กับ UITextViews ที่ไม่สามารถแก้ไขได้เท่านั้น! ยังไม่ได้ทดสอบกับตัวแก้ไข ...
return NO;
ใน- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
วิธีการที่เป็นตัวเลือกที่ดีกว่า
หากคุณต้องการปิดใช้งานการตัด / คัดลอก / วางในแอปพลิเคชันทั้งหมด UITextView
ของคุณคุณสามารถใช้หมวดหมู่กับ:
@implementation UITextView (DisableCopyPaste)
- (BOOL)canBecomeFirstResponder
{
return NO;
}
@end
มันช่วยประหยัดคลาสย่อย ... :-)
UITextView
ทำงานตามที่คาดไว้ตัวอย่างเช่นเมื่อแก้ไขได้และได้รับการสัมผัส มันมีมากที่จะลบล้างcanPerformAction:withSender:
; นั่นคือสิ่งที่โปรโตคอลมีไว้สำหรับ
นี่เป็นทางออกที่ดีที่สุดสำหรับฉัน:
UIView *overlay = [[UIView alloc] init];
[overlay setFrame:CGRectMake(0, 0, myTextView.contentSize.width, myTextView.contentSize.height)];
[myTextView addSubview:overlay];
[overlay release];
คำตอบ @rpetrich ใช้ได้ผลสำหรับฉัน ฉันกำลังโพสต์โค้ดที่ขยายออกเผื่อว่าจะช่วยประหยัดเวลาได้บ้าง
ในกรณีของฉันฉันไม่ต้องการป๊อปอัปใด ๆ แต่ฉันต้องการให้ UITextField สามารถเป็นผู้ตอบกลับคนแรกได้
ขออภัยคุณยังคงได้รับป๊อปอัปแว่นขยายเมื่อคุณแตะฟิลด์ข้อความค้างไว้
@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
สวิฟต์ 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)
}
}
หากคุณไม่ต้องการให้ UITextView เลื่อนวิธีแก้ปัญหาที่ง่ายที่สุดที่ไม่เกี่ยวข้องกับการแบ่งคลาสย่อยคือปิดการใช้งานการโต้ตอบของผู้ใช้สำหรับมุมมองข้อความ:
textField.userInteractionEnabled = NO;
วิธีที่ง่ายที่สุดคือสร้างคลาสย่อยของ UITextView ที่แทนที่ 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;
}
เมื่อฉันส่งคืน NO ใน canPerformAction บน iOS 7 ฉันจะได้รับข้อผิดพลาดมากมายเช่นนี้:
<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.
ทางออกของฉันมีดังต่อไปนี้:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
}];
return [super canPerformAction:action withSender:sender];
}
เคล็ดลับคือการซ่อนตัวควบคุมเมนูในรอบถัดไปบนคิวหลัก (หลังจากที่แสดง)
นี่เป็นวิธีที่ง่ายที่สุดในการปิดใช้งานเมนู Select / Copy / Paste ทั้งหมดใน UITextView
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[UIMenuController sharedMenuController].menuVisible = NO;
return NO;
}
เนื่องจาก iOS 7 มีคุณสมบัติใน UITextView:
@property(nonatomic,getter=isSelectable) BOOL selectable;
ซึ่งจะทำให้มุมมองไม่อนุญาตให้เลือกข้อความ ใช้งานได้ดีสำหรับฉัน
หากคุณต้องการแทนที่แป้นพิมพ์ด้วย a สมมติว่าUIPicker
ในฐานะที่เป็นinputView
(แน่นอนว่ามีแถบเครื่องมือเป็นinputAccesotyView
) วิธีแก้ปัญหานี้อาจช่วยได้ ...
textFieldShouldBeginEditing:
textField.userInteractionEnabled = NO;
UIPickerView
ตั้งค่าเป็นใช่เมื่อทำเช่นนี้คุณจะสามารถแตะUITextField
และแสดงตัวเลือกให้เลือกได้ในUIPickerView
ขณะนี้คุณUITextField
จะไม่ตอบสนองต่อเหตุการณ์การสัมผัสใด ๆ (ซึ่งรวมถึงการแตะค้างไว้เพื่อตัดคัดลอกและวาง) อย่างไรก็ตามคุณต้องจำไว้ว่าให้ตั้งค่ากลับเป็นใช่เมื่อคุณกำลังปิดUIPickerView
อย่างไรก็ตามคุณจะไม่สามารถเข้าถึงไฟล์UIPickerView
อีก
ช่วงเวลาเดียวที่ล้มเหลวคือเมื่อผู้ใช้เริ่มต้นด้วยการแตะค้างไว้UITextView
จากนั้นคุณจะเห็นตัดสำเนาแล้ววางอีกครั้งเป็นครั้งแรก นี่คือเหตุผลที่คุณควรตรวจสอบอินพุตของคุณอยู่เสมอ นี่เป็นวิธีที่ง่ายที่สุดที่ฉันคิดได้ ตัวเลือกอื่น ๆ คือการใช้UILabel
ข้อความที่อ่านอย่างเดียว UITextView
แต่คุณพลาดจำนวนมากของการทำงานที่ดีจาก
UITextView คลาสย่อย - รวดเร็ว 4.0
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
หากคุณต้องการที่จะปิดการใช้งานสำหรับป๊อปอัพUITextField
แล้วลองนี้วิธีการในการสลับUITextFieldDelegate
isUserInteractionEnabled
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = false
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
textField.isUserInteractionEnabled = true
return true
}
สิ่งนี้ได้ผลสำหรับฉัน ตรวจสอบให้แน่ใจว่าคุณกำลังโทรออกลาออกเฟิร์สเรสปอนเดอร์บน textView
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[self.textView resignFirstResponder];
return NO;
}
ฉันให้คำตอบที่ใช้งานได้ที่นี่เพื่อปิดใช้งานการเลือกข้อความ + แว่นขยายโดยยังคงเปิดใช้งานลิงก์ที่สามารถคลิกได้หวังว่าจะช่วย:
หลังจากพยายามเป็นเวลานานฉันสามารถหยุดการเลือกข้อความขยายและรักษาการตรวจจับข้อมูลได้ (ลิงก์ที่คลิกได้ ฯลฯ ) โดยการแทนที่ addGestureRecognizer บนคลาสย่อย UITextView อนุญาตให้มีเพียง UILongPressGestureRecognizer เท่านั้นที่ชะลอการสิ้นสุดการสัมผัส:
UIUnselectableTextView.m
-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && gestureRecognizer.delaysTouchesEnded)
{
[super addGestureRecognizer:gestureRecognizer];
}
}
สำหรับSwift 3เปลี่ยนเป็น:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
คุณสามารถแก้ไขได้ในสตอรีบอร์ดโดยยกเลิกการเลือกช่องเหล่านี้:
หรือคุณสามารถตั้งค่าโดยใช้โปรแกรมได้ดังนี้:
textView.selectable = false
textView.editable = false
ฉันได้ทำมัน เกี่ยวกับฉันUITextView
ฉันมีคนพิการตัดคัดลอกเลือก ฯลฯ ตัวเลือกได้อย่างง่ายดายมาก
ฉันวางไว้UIView
ที่เดียวกับที่ฉันวางไว้UITextView
แต่เปิดself.view
และเพิ่มtouchDelegate
วิธีการดังนี้:
(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;
}
}
}
และมันได้ผลสำหรับฉัน ขอบคุณ.
รวดเร็ว
textView.selectable = false // disable text selection (and thus copy/paste/etc)
ที่เกี่ยวข้อง
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.
หากคุณต้องการเพิ่มตัวเลือกที่กำหนดเองใน UITextView ของคุณ แต่ปิดการใช้งานฟังก์ชันที่มีอยู่นี่คือวิธีที่คุณทำบนSwift 3 :
หากต้องการปิดใช้งานการคัดลอกวางและตัด funcionality สร้างคลาสย่อยและลบล้างสิ่งต่อไปนี้:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
บน ViewController คุณมี CustomTextView ของคุณเพิ่มสิ่งต่อไปนี้เพื่อเพิ่มตัวเลือกของคุณ:
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)")
}
วิธีนี้จะปิดการใช้งานเมนู Select, Select All, Paste โดยสิ้นเชิง หากคุณยังคงได้รับการดำเนินการอื่น ๆ ให้เพิ่มสิ่งนั้นในเงื่อนไข if ดังต่อไปนี้
- (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];
}
คุณสามารถสร้างหมวดหมู่ดังนี้:
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
คลาสย่อยUITextView
และการลบล้าง- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
เป็นอีกหนึ่งความเป็นไปได้ที่จะปิดการทำงานที่ไม่ต้องการ
ใช้คลาสของgestureRecognizer
-object เพื่อตัดสินใจว่าควรเพิ่มการกระทำหรือไม่
(SWIFT)หากคุณต้องการเพียงแค่ช่องข้อความพื้นฐานโดยไม่มีตัวเลือกเมนูหรือแว่นขยายใด ๆ ให้สร้างคลาสย่อยของ UITextField ที่ส่งคืน false ไปยังท่าทางRecognizerShouldBegin:
class TextFieldBasic: UITextField {
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
การดำเนินการนี้จะข้ามฟังก์ชันการสัมผัสทั้งหมดในช่องข้อความ แต่ยังอนุญาตให้คุณใช้แป้นพิมพ์ป๊อปอัปเพื่อเพิ่ม / ลบอักขระได้
หากคุณใช้สตอรีบอร์ดเพียงแค่กำหนดคลาสที่สร้างขึ้นใหม่ให้กับฟิลด์ข้อความหรือหากคุณกำลังสร้างฟิลด์ข้อความโดยใช้โปรแกรม:
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)}
สวิฟต์ 3
ในการดำเนินการนี้คุณต้อง subclass UITextView ของคุณและใส่วิธีนี้
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 มีคุณสมบัติสองอย่างที่จะทำสิ่งที่คุณต้องการ: isSelectableและisEditable isEditable
การตั้งค่า isEditable เป็น false คุณจะหลีกเลี่ยงไม่ให้ผู้ใช้แก้ไขข้อความและการตั้งค่าisSelectable to false คุณจะหลีกเลี่ยงไม่ให้ผู้ใช้เลือกข้อความภายใน textView ของคุณดังนั้นสิ่งนี้จะป้องกันไม่ให้แสดงเมนูการทำงาน
โปรดค้นหาโค้ดตัวอย่างสำหรับการอ้างอิง:
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
}
ใช้func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { retrun bool }
แทน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
}
}
สร้างคลาสใหม่ด้วยชื่อ StopPasteAction.swift
import UIKit
class StopPasteAction: UITextField {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
เพิ่มคลาสใหม่กับ TextField ปัจจุบันของคุณ