React-Native之如何創(chuàng)建一個(gè)自適應(yīng)高度的TextInput

自適應(yīng)高度的多行文本輸入框AutoTextInput是一種常用需求,在RN官方文檔上就有其demo

class AutoExpandingTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      text: 'React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React. The focus of React Native is on developer efficiency across all the platforms you care about — learn once, write anywhere. Facebook uses React Native in multiple production apps and will continue investing in React Native.',
      height: 0,
    };
  }
  render() {
    return (
      <TextInput
        {...this.props}
        multiline={true}
        onContentSizeChange={(event) => {
          this.setState({height: event.nativeEvent.contentSize.height});
        }}
        onChangeText={(text) => {
          this.setState({text});
        }}
        style={[styles.default, {height: Math.max(35, this.state.height)}]}
        value={this.state.text}
      />
    );
  }
}

利用onContentSizeChange,在就在內(nèi)容內(nèi)容布局改變(如換行)的時(shí)候能獲取到當(dāng)前contentSize中的高度,然后通過state調(diào)整其input的高度。
原理很簡(jiǎn)單,但是這種寫法在Android上卻是有bug的,onContentSizeChange這個(gè)方法在Android上僅會(huì)初始render的的時(shí)候觸發(fā)一次,其后就不會(huì)在觸發(fā)了。目前我的RN版本為0.41.0,而Android試驗(yàn)了6.0和7.0。在github上也有相應(yīng)的#issue6552,于RN版本0.33就有了,預(yù)計(jì)以后是會(huì)解決的。
但是我們現(xiàn)在該如何避免這個(gè)bug呢,這時(shí)候需要利用另一個(gè)事件onChange,也是能取到contentSize的。不過onChange也有一個(gè)缺點(diǎn),他在非用戶輸入的情況是不會(huì)觸發(fā)的,也就是說我在TextInput帶有初始的defaultValue時(shí),無法改變組件的高度,會(huì)造成看不見的情況。這里要結(jié)合這兩種事件來解決。
順便再添加minHeight和maxHeight的一個(gè)完整的AutoTextInput如下

export default class AutoTextInput extends Component {
  constructor(props) {
    super(props);
    this.onContentSizeChange = this.onContentSizeChange.bind(this);
    this.onChange = this.onChange.bind(this);
    this.state = {
      height: 0,
    };
  }

  onContentSizeChange(event) {
    let height = event.nativeEvent.contentSize.height;
    this.changeHeight(height);
  }

  onChange(event) {
    if (Platform.OS === 'android') {
      let height = event.nativeEvent.contentSize.height;
      this.changeHeight(height);
    }
  }

  changeHeight(height) {
    let {
      minHeight = 16,
      maxHeight,
    } = this.props;
    if (height < minHeight) {
      height = minHeight;
    } else if (maxHeight && height > maxHeight) {
      height = maxHeight;
    }
    if (height !== this.state.height) {
      this.setState({height: height});
    }
  }

  render() {
    return (
      <TextInput
        {...this.props}
        multiline
        onContentSizeChange={this.onContentSizeChange}
        onChange={this.onChange}
        style={[this.props.style, {height: this.state.height}]}
      />
    )
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容