在TextInput React-Native上获取光标位置

时间:2015-06-21 04:29:50

标签: javascript react-native

有没有人对如何获得TextInput的插入位置有任何想法?我尝试了onSelectionChange并从DocumentSelectionState创建了一个事件发射器,但似乎都没有工作(无论我选择什么,它们都不会触发任何东西)。

例如:https://rnplay.org/apps/eZnvIA

5 个答案:

答案 0 :(得分:11)

onSelectionChange={(event) => console.log(event.nativeEvent.selection)}

答案 1 :(得分:1)

如果您愿意进行半冒险,可以更新react-native库以允许检索光标(x / y)坐标(相对于TextInput), onSelectionChange事件参数。

Full instructions for IOS AND Android。 (免责声明:我没有提出这个解决方案)

TLDR - IOS + ReactNative 0.49.1

node_modules/react-native/Libraries/Text/RCTTextSelection.h

/**
 * Object containing information about a TextInput's selection.
 */
@interface RCTTextSelection : NSObject

@property (nonatomic, assign, readonly) NSInteger start;
@property (nonatomic, assign, readonly) NSInteger end;
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
@property (nonatomic, assign, readonly) CGPoint cursorPosition;

- (instancetype)initWithStart:(NSInteger)start end:(NSInteger)end cursorPosition:(CGPoint)cursorPosition;
/* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

@end

node_modules/react-native/Libraries/Text/RCTTextSelection.m

@implementation RCTTextSelection

    /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
- (instancetype)initWithStart:(NSInteger)start end:(NSInteger)end cursorPosition:(CGPoint)cursorPosition
    /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
{
  if (self = [super init]) {
    _start = start;
    _end = end;
    /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
    _cursorPosition = cursorPosition;
    /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
  }
  return self;
}

@end

@implementation RCTConvert (RCTTextSelection)

+ (RCTTextSelection *)RCTTextSelection:(id)json
{
  if ([json isKindOfClass:[NSDictionary class]]) {
    NSInteger start = [self NSInteger:json[@"start"]];
    NSInteger end = [self NSInteger:json[@"end"]];
    /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
    CGPoint cursorPosition = CGPointMake(
      [self CGFloat:json[@"cursorPositionX"]],
      [self CGFloat:json[@"cursorPositionY"]]
    );
    return [[RCTTextSelection alloc] initWithStart:start
                                               end:end 
                                    cursorPosition:cursorPosition];
    /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
  }

  return nil;
}

@end

node_modules/react-native/Libraries/Text/RCTTextInput.m

- (RCTTextSelection *)selection
{
  id<RCTBackedTextInputViewProtocol> backedTextInput = self.backedTextInputView;

  UITextRange *selectedTextRange = backedTextInput.selectedTextRange;
  return [[RCTTextSelection new] initWithStart:[backedTextInput offsetFromPosition:backedTextInput.beginningOfDocument toPosition:selectedTextRange.start]
                                           end:[backedTextInput offsetFromPosition:backedTextInput.beginningOfDocument toPosition:selectedTextRange.end]
      /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
                                cursorPosition:[backedTextInput caretRectForPosition:selectedTextRange.start].origin];
      /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
}

...

- (void)textInputDidChangeSelection
{
  if (!_onSelectionChange) {
    return;
  }

  RCTTextSelection *selection = self.selection;
  _onSelectionChange(@{
    @"selection": @{
      @"start": @(selection.start),
      @"end": @(selection.end),
      /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
      @"cursorPositionX": @(selection.cursorPosition.x),
      @"cursorPositionY": @(selection.cursorPosition.y)
      /* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
    },
  });
}

答案 2 :(得分:0)

在react-native <= v0.56中,以下代码将选择作为{state:number,end:number}的对象。文本位置从0开始。例如,可能会发生{start:0,end:0}之类的选择,这意味着您的光标位于文本的第一个字符之前,并且未选择任何内容。当开始和结束不相等时,会出现另一种选择类型,例如{start:0,end:10},这意味着您选择文本的前10个字符。

如果您在textInput中使用react native v0.57.0或v0.57.1​​,请按照issue的方式进行操作,必须将multiline = {true}添加到所有正常工作中。

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, TextInput} from 'react-native';

type Props = {};
export default class App extends Component<Props> {

    constructor(props) {
        super(props)
        this.state = {
        selection: {start: 0, end: 0},
        text: 'This is a sample text',
    }
}
render() {
 return (
    <View style={styles.container}>
      <Text>{this.state.selection.start}, {this.state.selection.end}</Text>
      <TextInput
        style={{ width: 300, borderColor: 'gray', borderWidth: 1 }}
        onSelectionChange={({ nativeEvent: { selection } }) => {
          this.setState({ selection })
        }}
        onChangeText={(text) => this.setState({ text })}
        value={this.state.text}
      />
    </View>
    );
    }
}

结果是:

enter image description here

答案 3 :(得分:0)

要获取光标的位置,您唯一需要的就是 onSelectionChange https://reactnative.dev/docs/textinput#onselectionchange。 该函数将返回开始结束值。

答案 4 :(得分:-4)

首先,您可能希望使用onChange或甚至onChangeText事件。这将使你的警报开火。