【问题标题】:How to get the current number of lines in String of TextInput?如何获取 TextInput 字符串中的当前行数?
【发布时间】:2019-06-19 08:17:17
【问题描述】:

TextInput中输入文字后 我想知道TextInput 中的当前行数。 要么 目前strings的号码也是可以的。

我试过string.split('\n').length,但是这段代码没有检测到当文本大于屏幕时行自动递增。

如何获取行数

当我在Swift 中制作此功能时 使用string.enumerateLines 函数实现。

你们有类似的功能吗?

【问题讨论】:

    标签: react-native react-native-textinput


    【解决方案1】:

    据我所知,没有官方的方法可以获取当前使用的行数,但我有一个解决方法:

    我们利用TextInputonLayout 方法并跟踪当前使用的高度。我们需要两个状态变量:

    this.state = {
          height: 0, // here we track the currently used height
          usedLines: 0,// here we calculate the currently used lines 
        }
    

    onLayout:

      _onLayout(e) {
         console.log('e', e.nativeEvent.layout.height);
         // the height increased therefore we also increase the usedLine counter
         if (this.state.height < e.nativeEvent.layout.height) {
             this.setState({usedLines: this.state.usedLines+1}); 
         } 
         // the height decreased, we subtract a line from the line counter 
         if (this.state.height > e.nativeEvent.layout.height){
             this.setState({usedLines: this.state.usedLines-1}); 
         }
         // update height if necessary
         if (this.state.height != e.nativeEvent.layout.height){
             this.setState({height: e.nativeEvent.layout.height});
         }
    
      }
    

    渲染方法

      render() {
        console.log('usedLines', this.state.usedLines);
        return (
          <View style={styles.container}>
            <TextInput multiline style={{backgroundColor: 'green'}} onLayout={(e)=> this._onLayout(e)} />
          </View>
        );
      }
    

    工作示例:

    https://snack.expo.io/B1vC8dvJH

    【讨论】:

      【解决方案2】:

      对于 react-native 版本 >= 0.46.1

      您可以使用 onContentSizeChange 获得更准确的线路跟踪,例如使用如下反应挂钩:

           /**
           * used to tracker content height and current lines
           */
          const [contentHeightTracker, setContentHeightTracker] = useState<{
              height: number,
              usedLines: number;
          }>({
              height: 0,
              usedLines: 0
          });
      
          useEffect(() => {
              // console.log('used line change : ' + lineAndHeightTracker.usedLines);
              // console.log('props.extremeLines : ' + props.extremeLines);
              if (contentHeightTracker.usedLines === props.extremeLines) {
                  if (extremeHeight.current === undefined) {
                      extremeHeight.current = contentHeightTracker.height;
                  }
              }
              //callback height change
              if (contentHeightTracker.height !== 0) {
                  props.heightChange && props.heightChange(contentHeightTracker.height,
                      contentHeightTracker.usedLines >= props.extremeLines,
                      extremeHeight.current);
              }
          }, [contentHeightTracker]);
      
          const _onContentHeightChange = (event: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
              // console.log('event height : ', event.nativeEvent.contentSize.height);
              // console.log('tracker height : ', lineAndHeightTracker.height);
              // the height increased therefore we also increase the usedLine counter
              if (contentHeightTracker.height < event.nativeEvent.contentSize.height) {
                  setContentHeightTracker({
                      height: event.nativeEvent.contentSize.height,
                      usedLines: contentHeightTracker.usedLines + 1
                  });
              } else {
                  // the height decreased, we subtract a line from the line counter
                  if (contentHeightTracker.height > event.nativeEvent.contentSize.height) {
                      setContentHeightTracker({
                          height: event.nativeEvent.contentSize.height,
                          usedLines: contentHeightTracker.usedLines - 1
                      });
                  }
              }
          };
      
      render() {
          console.log('usedLines', this.state.usedLines);
          return (
            <View style={styles.container}>
              <TextInput 
                 multiline 
                 style={{backgroundColor: 'green'}} 
                 onContentSizeChange={_onContentHeightChange}
              />
            </View>
          );
        }
      

      【讨论】:

        【解决方案3】:

        如果用户:其他解决方案可能会失败:

        • 突出显示很多行并一次性删除它们
        • 一次粘贴很多行

        解决此问题的一种方法是将lineHeight 设置为&lt;TextInput&gt; 并使用onContentSizeChange 属性:

        <TextInput
            style={{
                lineHeight: 20,
            }}
            onContentSizeChange={e =>
                console.log(e.nativeEvent.contentSize.height / 20) // prints number of lines
            }
        />
        

        【讨论】:

          猜你喜欢
          • 2014-01-30
          • 2019-05-12
          • 2013-10-11
          • 2014-09-01
          • 1970-01-01
          • 2016-12-31
          • 1970-01-01
          • 1970-01-01
          • 2012-06-21
          相关资源
          最近更新 更多