模拟显示:React Native 中的内联

Posted

技术标签:

【中文标题】模拟显示:React Native 中的内联【英文标题】:Simulate display: inline in React Native 【发布时间】:2016-04-10 00:15:18 【问题描述】:

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

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

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

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

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

【问题讨论】:

在这个答案中有一个解决方案:***.com/a/45335695/3051080 你能告诉我,这是否如图所示工作?我正在尝试将图像放在两个文本之间,效果与您在图像中显示的效果相同。 【参考方案1】:

您可以通过将文本元素包装在其他文本元素中来获得此效果,就像将 span 包装在 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>

查看this 示例。

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

【讨论】:

请注意,添加 flexWrap: 'wrap' 会导致整个文本节点在换行时流到下一行,它不会导致部分文本保留在初始行,而其余的句子流向下一个。 paddingmargin 都不适用于内部 Texts 一个问题,这不允许改变 fontFamily :/ 除非您将每个单词分解为单独的文本元素,否则不会产生预期的效果。【参考方案2】:

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

【讨论】:

这行得通,只是显示了 React Native 还缺少多少。悲伤,只是悲伤。【参考方案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>

【讨论】:

【参考方案4】:

我有以下用例:

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

如果您无法以任何方式控制下划线(它有多近,它是什么颜色等等),这很简单 - 这让我穿过了兔子洞,最终想出了拆分每个单词的解决方案,并将其包装在单独的 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()>
                  valisLast ? '' : ' '
                </Text>
              </View>
            );
          

          return (
            <Text key=key style=getTextStyle()>
              partisLast ? '' : ' '
            </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>
    );
  

这是最终结果:

【讨论】:

可悲的是,这似乎是唯一“合理”的解决方案。啊!【参考方案5】:

试试这个,简单又干净。

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

结果:

Lorem ipsum dolor sit amet.

【讨论】:

以上是关于模拟显示:React Native 中的内联的主要内容,如果未能解决你的问题,请参考以下文章

突出显示 React-Native FlatList 中的选定项目

默认使用 React Native 打开 android 模拟器

React Native与夜神模拟器连接第一次白屏没有显示Welcome to React Native

React-native:图像未显示在 android 设备中;但在模拟器中完美显示

react-native IOS应用程序未在模拟器中显示资产

React-Native,Pdf 在 android 模拟器上显示,但在实际的 android 设备上出现错误