【问题标题】:How to show for text More/Less in React-Naitve (Javascript)如何在 React-Native (Javascript) 中显示更多/更少的文本
【发布时间】:2019-09-12 06:51:36
【问题描述】:

我正在开发 react-native 应用程序。其中,我们在 Text 上显示了一些描述,可能是行数。

所以,如果数据超过 3 行,我必须在展开时显示更多和更少。

        <FlatList
          style={styles.faltList}
          showsVerticalScrollIndicator
          data={data}
          extraData={this.state}
          renderItem={({ item, index }) => (
            <View style={styles.flatListCell}>
                <Text style={styles.description}>{item.description}</Text>
              </View>
            </View>
          )
          }
          ItemSeparatorComponent={() => (
            <View style={{ height: 10}} />
          )}
        />

我找到了 react-native-view-more-text 库,但我想通过自定义代码来实现它。

注意:我在 Flatlist 中显示该文本。

有什么建议吗?

【问题讨论】:

    标签: javascript react-native text react-native-flatlist


    【解决方案1】:
    import React from 'react';
    import PropTypes from 'prop-types';
    import AnchorText from '../AnchorText';
    
    import { StyledContainer, RegularText } from './styles';
    
    export default class Description extends React.Component {
          constructor(props) {
    super(props);
    this.state = {
      showMore: true,
    };
    }
    
     onClick = () => {
    this.setState({
      showMore: false,
    });
    };
    
     render() {
    const { description } = this.props;
    const { showMore } = this.state;
    if (!description) return null;
    
    return (
      <StyledContainer FD={'column'}>
        {showMore ? (
          <RegularText MT={1}>
            {description.slice(0, 150)}{' '}
            {description.length > 150 && (
              <AnchorText onClick={this.onClick} label=" .. Read more" />
            )}{' '}
          </RegularText>
        ) : (
            <RegularText MT={1}>{description}</RegularText>
        )}
      </StyledContainer>
    );
     }
    } 
    
    Description.propTypes = {
     description: PropTypes.string,
     };
    

    看看这个小部件

    【讨论】:

    • 这些 PropTypes,AnchorText 是什么?
    • 只是 Proptype 检查。忽略他们
    • 什么是 AnchorText?
    • 只是可点击的文本
    【解决方案2】:

    你可以简单地使用numberOfLines,这是一个&lt;Text&gt; prop:

    用于在计算文本后用省略号截断文本 布局,包括换行,这样总行数 不超过这个数字。

    而且,显然,一个足够的逻辑处理程序可以在您的state 中保存显示哪些文本以及截断哪些文本。

    让我们看一个我刚刚创建的示例:

    state = {
        textShown: -1,
      };
    
      toggleNumberOfLines = index => {
        this.setState({
          textShown: this.state.textShown === index ? -1 : index,
        });
      };
    
      render() {
        return (
          <View style={styles.container}>
            <FlatList
              data={[
                { key: 'a', description: longText },
                { key: 'b', description: longText },
                { key: 'c', description: longText },
              ]}
              renderItem={({ item, index }) => (
                <View style={styles.flatListCell}>
                  <Text
                    numberOfLines={this.state.textShown === index ? undefined : 3}
                    style={styles.description}>
                    {longText}
                  </Text>
                  <Text
                    onPress={() => this.toggleNumberOfLines(index)}
                    style={{ color: 'red' }}>
                    {this.state.textShown === index ? 'read less...' : 'read more...'}
                  </Text>
                </View>
              )}
            />
          </View>
        );
      }
    

    这里我使用state 将元素的索引保存在FlatList 中,如图所示。如果没有显示,则保存的值为-1。

    你可以在thissnack 中尝试它的行为,那(我希望)能重现你的情况。 让我知道这是否是您正在寻找的。 (嗨,Anilkumar,我们已经见过 :))

    【讨论】:

    • 谢谢。但是,如果我展开,数据与单元格标题重叠,并且在展开时间时,文本高度增加到上面而不是页脚增加,如何解决这个问题?
    • 还有一个问题,如果文本长度只有 3 行,那么我们不会显示更多/更少,但是,在这段代码中显示更多/更少,即使数据只有 3 行。
    • 第一个我认为是风格问题。第二个是我没有考虑过的问题,也不是那么容易解决,不过你可以看看this解决方案
    • 哦。谢谢@Milore
    【解决方案3】:

    我尝试过这种方式,希望对你和其他人有所帮助!

    const postTextContent = (props) => {
    const [textShown, setTextShown] = useState(false); //To show ur remaining Text
    const [lengthMore,setLengthMore] = useState(false); //to show the "Read more & Less Line"
    const toggleNumberOfLines = () => { //To toggle the show text or hide it
        setTextShown(!textShown);
    }
    
    const onTextLayout = useCallback(e =>{
        setLengthMore(e.nativeEvent.lines.length >=4); //to check the text is more than 4 lines or not
        // console.log(e.nativeEvent);
    },[]);
        
      return (
          <View style={styles.mainContainer}>
              <Text
                  onTextLayout={onTextLayout}
                  numberOfLines={textShown ? undefined : 4}
                  style={{ lineHeight: 21 }}>{Your Long Text}</Text>
    
                  {
                      lengthMore ? <Text
                      onPress={toggleNumberOfLines}
                      style={{ lineHeight: 21, marginTop: 10 }}>{textShown ? 'Read less...' : 'Read more...'}</Text>
                      :null
                  }
          </View>
      )
    }
    

    【讨论】:

    • 工作正常!谢谢
    • 如果我想内联 Read Less 或 Read More 怎么办?准确地说,在...被省略号添加后,我想添加 Read More 还是 Read Less?在这种情况下这个解决方案将如何工作
    • 效果很好,谢谢。只需注意条件必须大于 numberOfLines 并且不能大于或等于。
    • @Ankit onTextLayout 无法获取长度。如果我将 lengthMore 状态设为 true,那么这有效,但无论文本的长度是多少,阅读更多文本都会永久存在......知道如何使它工作吗? snack.expo.dev/vhn0ZM3Pn
    • 出于某种疯狂的原因,上述内容在 Snack 中不起作用,但在 AVD 中起作用。
    【解决方案4】:

    第一个实现很接近,但问题是当文本等于 3 行时会显示“阅读更多”按钮,因为没有更多文本,所以它不应该显示。我通过更新 state 中的行数以及检查文本是否已显示来修复它。

    const ReadMoreText = ({ readMoreStyle, text, textStyle }) => {
      const [showMoreButton, setShowMoreButton] = useState(false);
      const [textShown, setTextShown] = useState(false);
      const [numLines, setNumLines] = useState(undefined);
    
      const toggleTextShown = () => {
        setTextShown(!textShown);
      };
    
      useEffect(() => {
        setNumLines(textShown ? undefined : 3);
      }, [textShown]);
    
      const onTextLayout = useCallback(
        (e) => {
          if (e.nativeEvent.lines.length > 3 && !textShown) {
            setShowMoreButton(true);
            setNumLines(3);
          }
        },
        [textShown],
      );
    
      return (
        <>
          <Text onTextLayout={onTextLayout} numberOfLines={numLines} style={textStyle} ellipsizeMode="tail">
            {text}
          </Text>
    
          {showMoreButton ? (
            <Text onPress={toggleTextShown} style={readMoreStyle}>
              {textShown ? 'Read Less' : 'Read More'}
            </Text>
          ) : null}
        </>
      );
    };
    

    【讨论】:

    • 确实有这个解决方案,但是当我点击更大的文本时,应用程序似乎很慢
    【解决方案5】:

    check output of this code

    state = {
        textLenth: null,
        numberOfLines: 3,
    }
    
    handleSeeMore = () => {
        this.state.textLenth
        ? this.setState({numberOfLines: 0})
        : this.setState({numberOfLines: 3});
    };
    
    
         <Text
         numberOfLines={this.state.numberOfLines}
         onPress={() => this.handleSeeMore()}
         ellipsizeMode="middle"
         onTextLayout={({nativeEvent: {lines}}) =>
         this.setState({textLenth: lines.length === 3})
         }>
             This Gig Take a glance at the showcase of our artistic work:
             Modern and Trendy Logo Artworkslkjfkljf ksnfksfnsf Mascot &
             Custom Logo efdfg Artworks:lk knnk 'Explore the
             ultimate Experience..!' To fulfill your designing needs, 
             Make us Graphically Yours...!! Why Team StrideInIt? We 
             believe in our
         {'                      '}
             {this.state.textLenth && (
             <Text
             color="red"
             onPress={() => this.setState({numberOfLines: 0})}>
                 see more
             </Text>
             )}
         </Text>
    

    【讨论】:

      【解决方案6】:

      看看我的解决方案,我没有使用文本行,而是使用了文本长度。

      import React, {useState} from 'react';
      import {Text, View, Image, TouchableOpacity, StyleSheet} from 'react-native';
      
      const PostContent = () => {
        const postDescription =
          "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
        const [showMore, setShowMore] = useState(false);
      
        return (
          <View style={styles.postContentContainer}>
            {postDescription.length > 120 ? (
              showMore ? (
                <TouchableOpacity onPress={() => setShowMore(!showMore)}>
                  <Text style={styles.postDescription}>{postDescription}</Text>
                  <Text style={styles.seeMore}>Show less</Text>
                </TouchableOpacity>
              ) : (
                <TouchableOpacity onPress={() => setShowMore(!showMore)}>
                  <Text style={styles.postDescription}>
                    {`${postDescription.slice(0, 120)}... `}
                  </Text>
                  <Text style={styles.seeMore}>Show more</Text>
                </TouchableOpacity>
              )
            ) : (
              <Text style={styles.postDescription}>{postDescription}</Text>
            )}
          </View>
        );
      };
      
      export default PostContent;
      
      const styles = StyleSheet.create({
        postContentContainer: {
          // borderWidth: 1,
          // borderColor: 'red',
          flexDirection: 'column',
        },
      
        postMedia: {
          //borderWidth: 1,
          //borderColor: 'red',
          width: '100%',
          height: 280,
          resizeMode: 'cover',
        },
      
        postDescription: {
          paddingTop: 15,
          paddingHorizontal: 15,
          color: colors.text.black,
          fontFamily: fonts.family.body,
          fontSize: fonts.fontSizes.button,
          fontWeight: fonts.fontWeights.thin,
        },
      
        seeMore: {
          paddingHorizontal: 15,
          color: colors.text.grey,
          fontStyle: 'italic',
          textDecorationLine: 'underline',
          fontFamily: fonts.family.body,
          fontSize: fonts.fontSizes.button,
          fontWeight: fonts.fontWeights.thin,
        },
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-09
        • 2020-06-18
        • 2020-04-20
        • 1970-01-01
        • 1970-01-01
        • 2018-07-27
        • 1970-01-01
        • 2021-12-20
        相关资源
        最近更新 更多