模拟显示: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'
会导致整个文本节点在换行时流到下一行,它不会导致部分文本保留在初始行,而其余的句子流向下一个。
padding
和 margin
都不适用于内部 Text
s
一个问题,这不允许改变 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" > 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 设备中;但在模拟器中完美显示