CSS 模拟显示:在 React Native 中内联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34624100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simulate display: inline in React Native
提问by Brent Traut
React Native doesn't support the CSS display
property, and by default all elements use the behavior of display: flex
(no inline-flex
either). Most non-flex layouts can be simulated with flex properties, but I'm flustered with inline text.
React Native 不支持 CSSdisplay
属性,并且默认情况下所有元素都使用display: flex
(不支持inline-flex
)的行为。大多数非 flex 布局可以用 flex 属性模拟,但我对内联文本感到困惑。
My app has a container that contains several words in text, some of which need formatting. This means I need to use spans to accomplish the formatting. In order to achieve wrapping of the spans, I can set the container to use flex-wrap: wrap
, but this will only allow wrapping at the end of a span rather than the traditional inline behavior of wrapping at word breaks.
我的应用程序有一个容器,其中包含文本中的几个单词,其中一些需要格式化。这意味着我需要使用跨度来完成格式化。为了实现跨度的换行,我可以将容器设置为 use flex-wrap: wrap
,但这将只允许在跨度的末尾换行,而不是在断字处换行的传统内联行为。
The problem visualized (spans in yellow):
问题可视化(跨度为黄色):
(via http://codepen.io/anon/pen/GoWmdm?editors=110)
(通过http://codepen.io/anon/pen/GoWmdm?editors=110)
Is there a way to get proper wrapping and true inline simulation using flex properties?
有没有办法使用 flex 属性获得正确的包装和真正的内联模拟?
回答by Nader Dabit
You can get this effect by wrapping text elements in other text elements the way you would wrap a span in a div or another element:
您可以通过将文本元素包装在其他文本元素中来获得这种效果,就像在 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>
You can also get this effect by declaring a flexDirection:'row' property on the parent along with a flexWrap: 'wrap'. The children will then display inline:
您还可以通过在父级上声明 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>
Check out thisexample.
看看这个例子。
回答by bezoerb
You can only nest text nodes without using flex to get the desired effect. Like this: https://facebook.github.io/react-native/docs/text
您只能嵌套文本节点而不使用 flex 来获得所需的效果。像这样:https: //facebook.github.io/react-native/docs/text
<Text style={{fontWeight: 'bold'}}>
I am bold
<Text style={{color: 'red'}}>
and red
</Text>
</Text>
回答by Kristfal
I haven't found a proper way to inline text blocks with other content. Our current "hackish" workaround is to split every single word in a text string into its own block so flexWrap wraps properly for each word.
我还没有找到将文本块与其他内容内联的正确方法。我们当前的“hackish”解决方法是将文本字符串中的每个单词拆分为自己的块,以便 flexWrap 为每个单词正确换行。
回答by Erti-Chris Eelmaa
I had the following use case:
我有以下用例:
I needed a text that can wrap with different sizes, and throughout that text, I wanted to underscore some of the words (to indicate that they are clickable).
我需要一个可以用不同大小换行的文本,并且在整个文本中,我想对一些单词加下划线(以表明它们是可点击的)。
It's quite simple expect for the case that you can't control the underline in any way (how close is it, what color is it, so on) - this led me through the rabbit hole, and eventually coming up with the solution of splitting every word, and wrapping it in separate Text component, wrapped with View.
对于您无法以任何方式控制下划线(它有多近,它是什么颜色等)的情况,这是非常简单的期望 - 这使我通过了兔子洞,并最终想出了拆分的解决方案每个单词,并将其包装在单独的 Text 组件中,用 View 包装。
I'll paste the code here:
我将在这里粘贴代码:
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>
);
}
}
and usage:
和用法:
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>
);
}
this is the end result:
这是最终结果: