开发者

UITextView disabling text selection

I'm having a hard time getting the UITextView to disable the selecting of the text.

I've tried:

canCancelContentTouches = YES;

I've tried subclassing and overwriting:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender   

(But that gets called only After the selection)

- (BOOL)touchesShouldCancelInContentView:(UIView *)view;  

(I don't see that getting fired at all)

- (BOOL)touchesShouldBegin:(NSSet *)touches
                 withEvent:(UIEvent *)event
             inContentView:(UIView *)view; 

(I don't see that getting fir开发者_StackOverflow中文版ed either)

What am I missing?


Issue How disable Copy, Cut, Select, Select All in UITextView has a workable solution to this that I've just implemented and verified:

Subclass UITextView and overwrite canBecomeFirstResponder:

- (BOOL)canBecomeFirstResponder {
    return NO;
}

Note that this disables links and other tappable text content.


I've found that calling

[textView setUserInteractionEnabled:NO];

works quite well.


UITextView's selectable property:

This property controls the ability of the user to select content and interact with URLs and text attachments. The default value is YES.


Swift 4, Xcode 10

This solution will

  • disable highlighting
  • enable tapping links
  • allow scrolling

Make sure you set the delegate to YourViewController

yourTextView.delegate = yourViewControllerInstance

Then

extension YourViewController: UITextViewDelegate {

    func textViewDidChangeSelection(_ textView: UITextView) {
        if #available(iOS 13, *) {
            textView.selectedTextRange = nil
        } else {
            view.endEditing(true)
        }
    }

}


Swift 4, Xcode 10:

If you want to make it so the user isn't able to select or edit the text.

This makes it so it can not be edited:

textView.isEditable = false

This disables all user interaction:

textView.isUserInteractionEnabled = false

This makes it so that you can't select it. Meaning it will not show the edit or paste options. I think this is what you are looking for.

textView.isSelectable = false


It sounds like what you actually want is a giant UILabel inside a UIScrollView, and not a UITextView.

update: if you are on newer versions of iOS UILabel now has a lines property:

Multiple lines of text in UILabel


If you just want to prevent it from being edited, then set the UITextView's "editable" property to NO/False.

If you're trying to leave it editable but not selectable, that's going to be tricky. You might need to create a hidden textview that the user can type into and then have UITextView observe that hidden textview and populate itself with the textview's text.


To do this first subclass the UITextView

and in the implementation do the following

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
    self.selectable = NO;
}

- (void)touchesCancelled:(nullable NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
        self.selectable = YES;
 }

this should work fine,


Did you try setting userInteractionEnabled to NO for your UITextView? But you'd lose scrolling too.

If you need scrolling, which is probably why you used a UITextView and not a UILabel, then you need to do more work. You'll probably have to override canPerformAction:withSender: to return NO for actions that you don't want to allow:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    switch (action) {
        case @selector(paste:):
        case @selector(copy:):
        case @selector(cut:):
        case @selector(cut:):
        case @selector(select:):
        case @selector(selectAll:):
        return NO;
    }
    return [super canPerformAction:action withSender:sender];
}

For more, UIResponderStandardEditActions .


You can disable text selection by subclassing UITextView.

The below solution is:

  • compatible with isScrollEnabled
  • compatible with loupe/magnifier
  • but not compatible with links (see here for a solution compatible with links)
/// Class to disallow text selection
/// while keeping support for loupe/magnifier and scrolling
/// https://stackoverflow.com/a/49428248/1033581
class UnselectableTextView: UITextView {

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        commonInit()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }
    private func commonInit() {
        // prevents selection from loupe/magnifier (_UITextSelectionForceGesture), multi tap, tap and a half, etc.
        // without losing the loupe/magnifier or scrolling
        // but we lose taps on links
        addSubview(transparentOverlayView)
    }
    let transparentOverlayView: UIView = {
        $0.backgroundColor = .clear
        $0.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        return $0
    }(UIView())
    override var contentSize: CGSize {
        didSet {
            transparentOverlayView.frame = CGRect(origin: .zero, size: contentSize)
        }
    }

    // required to prevent blue background selection from any situation
    override var selectedTextRange: UITextRange? {
        get { return nil }
        set {}
    }
}


For swift, there is a property called "isSelectable" and its by default assign to true

you can use it as follow:

textView.isSelectable = false
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜