R. Lallier
R. Lallier

Reputation: 21

React Native onTextLayout with overflow hidden

I'm trying to build an animated "See More/Discard" button in my React Native App. I was planning to use onLayout or onTextLayout methods to get the height of my text, then using animated and overflow: "hidden" to display it on click of a button. Here's what the code looks like :

      <Animated.View style={{overflow: "hidden", height: heightAnim }}>
          <Text
            onTextLayout={({ nativeEvent: { lines } }) => {
              //We set the maxHeight to number of lines * the height of a line
              setContentHeight(lines.length * 14);
            }}
          >
            {description}
            //Description can range between 0 to 15 lines
          </Text>
      </Animated.View>
      <TouchableWithoutFeedback onPress={() => handleOpen()}>
        <Text>
          {open ? "Discard" : "See More"}
        </Text>
      </TouchableWithoutFeedback>

However, onLayout and onTextLayout only give me the size of the text that is visible on the screen. To give you an example, if the text lasts 14 lines and I initially display 2 lines of height 14, onLayout will return a height of 28, and onTextLayout lines will only return me the 2 first lines. This result in the maxHeight of my animation being also 28, so the hidden text remains hidden.

How can I access the height of all the height/lines of my text, including the hidden part?

Thank you for your help!

Upvotes: 2

Views: 6555

Answers (2)

Balalen
Balalen

Reputation: 498

You can use this simple way, it works fine but if you need to dynamically check if the text has more than 1 line you need to use onTextLayout and check on it.

   const [lines, setLines] = useState(1)
    
<View>

   <Text numberOfLines={lines}>This is some long text here This is some long 
   text here This is some long text here This is some long text here This is 
   some long text here This is some long text here This is some long text here 
   This is some long text here This is some long text here This is some long 
   text here This is some long text here This is some long text here 
   </Text>

   <TouchableOpacity onPress={() => {
      lines == 999 ? setLines(1) : setLines(999)
   }}>
      <Text style={{ color: 'blue' }}>{lines == 999 ? "Less" : "More"}</Text>
   </TouchableOpacity>

</View>

UPDATE:

or what you can do is wrap the text into the TouchableOpacity and when press on it it will expand like this

const [lines, setLines] = useState(1)
    
<View>


   <TouchableOpacity onPress={() => {
      lines == 999 ? setLines(1) : setLines(999)
   }}>
             <Text numberOfLines={lines}>This is some long text here This is some long 
   text here This is some long text here This is some long text here This is 
   some long text here This is some long text here This is some long text here 
   This is some long text here This is some long text here This is some long 
   text here This is some long text here This is some long text here 
   </Text>

   </TouchableOpacity>

</View>

Upvotes: 0

fenghengzhi
fenghengzhi

Reputation: 61

<View>
  <ScrollView style={{height:0}}>
    <Text onTextLayout={(e)=>{/* measure the text here */}}>{text}</Text>
  </ScrollView>
  <Text>{text}</Text>
</View>

you can render the text twice,one of the text wrapped with a ScrollView which height is 0. Then you can measure the all the height/lines of the text

Upvotes: 4

Related Questions