How to move cursor to the beginning of the current

2019-07-04 17:35发布

问题:

I want to have an insert tab button for my UITextView so that users be able to insert a tab at beginning of the current line. No matter where the cursor is in the line, the tab should be inserted at the beginning of the line, and after that the cursor must go to the end of the line.

Is it possible ?

回答1:

I have no luck with positionFromPosition:inDirection:offset: and characterRangeByExtendingPosition:inDirection:.

But this works fine for me:

UITextRange *range = [textView selectedTextRange];
CGRect rect = [textView caretRectForPosition:range.start];
UITextPosition *start = [textView closestPositionToPoint:CGPointMake(0, rect.origin.y)];
[textView setSelectedTextRange:[textView textRangeFromPosition:start toPosition:start]];

UPD: the code above is tested on iOS7 and earlier. And can no longer work with iOS9. Actually, I have some bugs in my text-editing app running on iOS9-devices. I'll update my answer after fixing my app.



回答2:

UITextView implements the UITextInput protocol, which has a whole bunch of methods for determining positions of text. I'm not sure about this, but perhaps you can call:

  1. selectedTextRange to get the caret position.
  2. positionFromPosition:inDirection:offset: with UITextLayoutDirectionLeft to find the range to the start of the current line. (This I'm not sure about; maybe characterRangeByExtendingPosition:inDirection: would work better?)
  3. Use textRangeFromPosition:toPosition: to get a range for the start of the lin.
  4. Use replaceRange:withText: to insert a tab.

There might be other methods in that protocol that would let you figure that out if that doesn't work.

Edit: Seems that UITextView only implements UITextInput as of iOS 5. If you're targeting before that, I'm not sure what to suggest.



回答3:

I'll add the code that I've been using to move the cursor to the beginning of the line (homeTap) as it addresses some of the comments within @zxcat's answer, regarding the cursor being moved to the beginning of previous line rather than the current line:

- (void)homeTap:(id)s {
    UITextRange* range = [_textView selectedTextRange];
    CGRect rect = [_textView caretRectForPosition:range.start];
    float halfLineHeight = _textView.font.lineHeight / 2.0;
    UITextPosition* start = [_textView closestPositionToPoint:CGPointMake(0, rect.origin.y + halfLineHeight)];
    [_textView setSelectedTextRange:[_textView textRangeFromPosition:start toPosition:start]];
}

Specifically, I add halfLineHeight to rect.origin.y to make sure the result from closestPositionToPoint is for the current line.