模拟显示:在 React Native 中内联

IT技术 css reactjs flexbox react-native
2021-03-29 23:46:03

React Native 不支持 CSSdisplay属性,并且默认情况下所有元素都使用display: flex(不支持inline-flex的行为大多数非 flex 布局都可以用 flex 属性模拟,但我对内嵌文本感到困惑。

我的应用程序有一个容器,其中包含文本中的多个单词,其中一些需要格式化。这意味着我需要使用跨度来完成格式化。为了实现跨度的换行,我可以将容器设置为 use flex-wrap: wrap,但这将只允许在跨度的末尾换行,而不是在断字处换行的传统内联行为。

问题可视化(跨度为黄色):

在此处输入图片说明

(通过http://codepen.io/anon/pen/GoWmdm?editors=110

有没有办法使用 flex 属性获得正确的包装和真正的内联模拟?

5个回答

您可以通过将文本元素包装在其他文本元素中来获得这种效果,就像在 div 或其他元素中包装跨度一样:

<View>
  <Text><Text>This writing should fill most of the container </Text><Text>This writing should fill most of the container</Text></Text>       
</View>

您还可以通过在父级上声明 flexDirection:'row' 属性以及 flexWrap:'wrap' 来获得这种效果。然后子项将显示内联:

<View style={{flexDirection:'row', flexWrap:'wrap'}}>
  <Text>one</Text><Text>two</Text><Text>Three</Text><Text>Four</Text><Text>Five</Text>
</View>

看看这个例子。

https://rnplay.org/apps/-rzWGg

请注意,添加flexWrap: 'wrap'会导致整个文本节点流到下一行,如果它会换行,它不会导致部分文本保留在初始行上,而句子的其余部分则流到下一行。
2021-05-24 23:46:03
一个问题,这不允许更改 fontFamily :/
2021-06-10 23:46:03
除非您将每个单词分解为单独的文本元素,否则这不会产生预期的效果。
2021-06-14 23:46:03
对内部s既不工作padding也不margin工作Text
2021-06-16 23:46:03

我还没有找到将文本块与其他内容内联的正确方法。我们当前的“hackish”解决方法是将文本字符串中的每个单词拆分为自己的块,以便 flexWrap 为每个单词正确换行。

这有效并且仅显示 React Native 还缺少多少。难过,只是难过。
2021-05-23 23:46:03

您只能嵌套文本节点而不使用 flex 来获得所需的效果。像这样:https : //facebook.github.io/react-native/docs/text

<Text style={{fontWeight: 'bold'}}>
  I am bold
  <Text style={{color: 'red'}}>
    and red
  </Text>
</Text>

我有以下用例:

我需要一个可以用不同大小换行的文本,并且在整个文本中,我想对一些单词加下划线(以表明它们是可点击的)。

对于您无法以任何方式控制下划线(它有多近,它是什么颜色等)的情况,这是非常简单的期望 - 这使我通过了兔子洞,并最终想出了拆分的解决方案每个单词,并将其包装在单独的 Text 组件中,用 View 包装。

我将在这里粘贴代码:



import React from 'react';
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';
import Colors from '../../styles/Colors';
import Fonts from '../../styles/Fonts';

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

export default class SaltText extends React.Component {

  getTheme (type) {

    if (type === 'robomonoregular10gray') {
      return {
          fontSize: Fonts.SIZES.TEN,
          fontFamily: Fonts.ROBOTOMONO_REGULAR,
          color: Colors.getColorOpacity(Colors.GRAY, 70),
          lineHeight: Fonts.SIZES.TEN + 10
      };
    }

    throw new Error('not supported');
  }

  splitText (text) {
    const parts = [];
    const maps = [];

    let currentPart = '';
    let matchIndex = 0;

    for (const letter of text) {

      const isOpening = letter === '[';
      const isClosing = letter === ']';

      if (!isOpening && !isClosing) {
        currentPart += letter;
        continue;
      }

      if (isOpening) {
        parts.push(currentPart);
        currentPart = '';
      }

      if (isClosing) {
        parts.push(`[${matchIndex}]`);
        maps.push(currentPart);
        currentPart = '';
        matchIndex++;
      }
    }

    const partsModified = [];
    for (const part of parts) {
      const splitted = part
        .split(' ')
        .filter(f => f.length);

      partsModified.push(...splitted);
    }

    return { parts: partsModified, maps };
  }

  render () {

    const textProps = this.getTheme(this.props.type);
    const children = this.props.children;

    const getTextStyle = () => {
      return {
        ...textProps,
      };
    };

    const getTextUnderlineStyle = () => {
      return {
        ...textProps,
        borderBottomWidth: 1,
        borderColor: textProps.color
      };
    };

    const getViewStyle = () => {
      return {
        flexDirection: 'row',
        flexWrap: 'wrap',
      };
    };

    const { parts, maps } = this.splitText(children);

    return (
      <View style={getViewStyle()}>
        {parts.map((part, index) => {

          const key = `${part}_${index}`;
          const isLast = parts.length === index + 1;

          if (part[0] === '[') {
            const mapIndex = part.substring(1, part.length - 1);
            const val = maps[mapIndex];
            const onPressHandler = () => {
              this.props.onPress(parseInt(mapIndex, 10));
            };
            return (
              <View key={key} style={getTextUnderlineStyle()}>
                <Text style={getTextStyle()} onPress={() => onPressHandler()}>
                  {val}{isLast ? '' : ' '}
                </Text>
              </View>
            );
          }

          return (
            <Text key={key} style={getTextStyle()}>
              {part}{isLast ? '' : ' '}
            </Text>
          );
        })}
      </View>
    );
  }
}

和用法:

  renderPrivacy () {

    const openTermsOfService = () => {
      Linking.openURL('https://reactnativecode.com');
    };

    const openPrivacyPolicy = () => {
      Linking.openURL('https://reactnativecode.com');
    };

    const onUrlClick = (index) => {
      if (index === 0) {
        openTermsOfService();
      }

      if (index === 1) {
        openPrivacyPolicy();
      }
    };

    return (
      <SaltText type="robomonoregular10gray" onPress={(index) => onUrlClick(index)}>
        By tapping Create an account or Continue, I agree to SALT\'s [Terms of Service] and [Privacy Policy]
      </SaltText>
    );
  }

这是最终结果:

例子

可悲的是,这似乎是唯一“合理”的解决方案。啊!
2021-06-07 23:46:03

试试这个,简单又干净。

<Text style={{ fontFamily: 'CUSTOM_FONT', ... }}>
   <Text>Lorem ipsum</Text>
   <Text style={{ color: "red" }}>&nbsp;dolor sit amet.</Text>
</Text>

结果:

Lorem ipsum dolor sit amet.