模拟显示:在React Native中内联

时间:2016-01-06 01:13:51

标签: css reactjs flexbox react-native

React Native不支持CSS display属性,默认情况下,所有元素都使用display: flex的行为(无inline-flex)。大多数非flex布局都可以使用flex属性进行模拟,但是我对内联文本感到慌乱。

我的应用有一个容器,其中包含几个文字,其中一些需要格式化。这意味着我需要使用跨度来完成格式化。为了实现跨度的包装,我可以将容器设置为使用flex-wrap: wrap,但这只允许在跨度结束时换行,而不是在换行符时包装的传统内联行为。

问题可视化(以黄色显示):

enter image description here

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

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

5 个答案:

答案 0 :(得分:65)

您可以通过将文本元素包装在div或其他元素中的span的方式来包装其他文本元素来获得此效果:

<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来获得此效果:&#39; row&#39;父母的属性以及flexWrap:&#39; wrap&#39;。然后孩子们将显示内联:

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

查看this示例。

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

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

答案 3 :(得分:1)

我有以下用例:

我需要一个可以用不同大小包裹的文本,并且在整个文本中,我都想强调一些单词(以表示它们是可单击的)。

很简单的情况是,您无法以任何方式控制下划线(它的接近程度,颜色是什么,等等)-这使我穿过了兔子洞,最终想到了拆分每个单词并将其包装在单独的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>
    );
  }

这是最终结果:

enter image description here

答案 4 :(得分:1)

试试这个,简单又干净。

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

结果:

Lorem ipsum dolor sit amet.