仿抖音,输入#号,将触发标签选择,标签文案 颜色为蓝色
标签规则:`#(至少1个字符)`
调研:
iOS的TextField可以设定attributedString富文本,但RN的TextInput是不具备的。
方案:
TextInput上浮一个style大小一致的Text,TextInput文字颜色设为透明,Text内嵌套 style为蓝色的Text 用来展示`#任意(至少1个)字符`
代码:
import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet } from 'react-native';
const App = () => {
const [text, setText] = useState('');
const handleTextChange = (inputText) => {
// 检测输入字符串中是否包含 "#"
if (inputText.includes('#')) {
// 将包含 "#任意(至少1个)字符" 的部分替换为带有蓝色样式的文本组件
const parts = inputText.split(/(?=#|\s)/g);
console.log('parts: ', parts);
const formattedText = parts.map((part, index) => {
return part.includes('#') && part.length > 1 ? (
<Text
onPress={() => {
console.log('click part:', part);
}}
key={index}
style={{ color: 'blue' }}>
{part}
</Text>
) : part;
});
// 设置更新后的文本
setText(formattedText);
} else {
// 输入字符串不包含 "#文字",直接设置文本
setText(inputText);
}
};
return (
<View style={{ flex: 1, backgroundColor: 'pink', marginTop: 100 }}>
<TextInput
style={[styles.text, { borderWidth: 1, borderColor: 'gray', width: '100%', padding: 0, color: 'rgba(0,0,0,0)' }]}
onChangeText={handleTextChange}
multiline={true}
>
<Text style={{ color: 'yellow' }}>{text}</Text>
</TextInput>
<Text style={{ color: 'yellow' }}>{text}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
borderWidth: 1,
borderColor: 'gray',
padding: 10,
marginTop: 20,
},
text: {
fontSize: 16,
lineHeight: 20
},
});
export default App;
如果 标签规则改为仿微博:`#(至少1个字符)#`
const convertRichText = (inputText) => {
// 检测输入字符串中是否包含 "#"
if (inputText?.includes("#")) {
// 将包含 "#任意(至少1个)字符#" 的部分替换为带有蓝色样式的文本组件
const parts = inputText.split(/(#[^#]+\n)|(#[^#]+#)/g);
// console.log('parts: ', parts);
let lastPart = "";
const formattedText = parts.map((part, index) => {
if (index + 1 == parts.length) lastPart = part;
if (!part) return "";
return (
<Text
key={index}
style={
part.startsWith("#") && part.endsWith("#") && part.length > 2
? { color: "#3C73FF" }
: {}
}
>
{part}
</Text>
);
});
// 设置更新后的文本
return { content: formattedText, lastPart: lastPart };
} else {
// 输入字符串不包含 "#文字",直接设置文本
return { content: inputText };
}
};
其中,lastPart 用于判断 末尾是否是 #,方便去触发 联想标签or弹窗选择标签...