我目前在react-native中编写一个新闻阅读器应用程序,并希望将文章的第一个字母设置为首字母,如下所示:
对于我的第一次尝试,我使用嵌套文本方法。代码附在下面。这是我目前的结果:
渲染函数中的代码:
<View style={styles.container}>
<Text style={styles.text}>
<Text style={styles.initial}>W</Text>
<Text>
elcome to React Native! To get started, edit index.android.js To get started, edit index.android.js To get started, edit index.android.js
</Text>
</Text>
</View>
我的样式表:
const fontSize = 14;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
initial: {
fontSize: fontSize * 2,
},
text: {
fontSize: fontSize,
color: '#333333',
},
});
我的问题: 如何设计我的第一个字符以获得漂亮的首字母?
环境
您也可以尝试这种方式,为父文本元素添加常规样式,为“W”文本子元素添加所需样式。
export default class DemoProject extends Component {
render() {
return (
<View style={styles.container}>
*<Text>
<Text style={[styles.textCommon, styles.firstLetter]}>W</Text>
elcome</Text>*
</View>
);
}
}
text: {
fontSize: fontSize,
color: '#333333',
}
这是一种方法:
export default class DemoProject extends Component {
render() {
return (
<View style={styles.container}>
<Text style={[styles.textCommon, styles.firstLetter]}>W</Text>
<Text>elcome</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
flexDirection: 'row'
},
textCommon: {
color: '#333333',
},
firstLetter: {
fontSize: 23,
}
});
对于 2023 年遇到此问题的任何人,我没有找到任何好的解决方案。所以我自己用一个专用的组件实现了它。 希望我们能得到更好的解决方案,就像
::first-letter
中的 CSS
一样
我正在使用
twrnc
,但您可以轻松地将样式实现与您正在使用的样式进行交换。
简而言之,这里发生的事情是,当给定文本时,我计算布局的宽度,然后从中获取第一句和第二句,考虑到第一个字符的长度,当我完成获取这些文本时,我计算布局的重置文本数据。
interface TextWithFirstLetterSpanProps extends ViewProps {
text: string;
fontSize?: number;
lineHeight?: number;
}
export default function ({
text,
fontSize = 17,
lineHeight = 1.4,
...viewProps
}: TextWithFirstLetterSpanProps) {
const [width, setWidth] = useState(0);
const onLayout = (event: LayoutChangeEvent) => {
const { width } = event.nativeEvent.layout;
setWidth(width);
};
const firstLetter = useMemo(() => text.charAt(0), [text]);
const { firstSentence, secondSentence, rest } = useMemo(() => {
let sentenceBuffer = '';
const widthWithoutFirstLetter = width - fontSize * 2;
let secondSentence = '';
let rest = '';
const words = text.split(' ');
words[0] = words[0].slice(1);
let firstSentence = '';
while (words.length > 0) {
const word = words.shift() ?? '';
if (firstSentence && secondSentence) {
rest += ` ${word}`;
continue;
}
if (((sentenceBuffer.length + word.length) * fontSize) / 2 < widthWithoutFirstLetter) {
sentenceBuffer += ` ${word}`;
} else {
if (firstSentence === '') {
firstSentence = sentenceBuffer;
} else if (secondSentence === '') {
secondSentence = sentenceBuffer;
} else {
rest += `${sentenceBuffer}`;
}
sentenceBuffer = word;
}
}
return {
firstSentence,
secondSentence,
rest,
};
}, [text, width]);
return (
<View onLayout={onLayout} {...viewProps}>
<View style={tw.style(`flex flex-row text-base gap-[0.3]`)}>
<Text
style={tw.style(`font-tiemposHeadline uppercase mt-1`, {
fontSize: fontSize * 2 * lineHeight,
lineHeight: fontSize * 2 * lineHeight,
})}
>
{firstLetter}
</Text>
<View>
<Text
style={tw.style({
fontSize: fontSize,
lineHeight: fontSize * lineHeight,
})}
>
{firstSentence}
</Text>
<Text
style={tw.style({
fontSize: fontSize,
lineHeight: fontSize * lineHeight,
})}
>
{secondSentence}
</Text>
</View>
</View>
<Text
style={tw.style({
fontSize: fontSize,
lineHeight: fontSize * lineHeight,
})}
>
{rest}
</Text>
</View>
);
}