I'm trying to make a TextInput
with a non-standard placeholder
, because I need formatting and the normal, built-in TextInput placeholder
doesn't work for me.
In order for the user to start writing from the beginning of the line, as with the normal placeholder, I set the cursor at the beginning of selection={TEXT ? null: {start: 0}
. When the user types further, the cursor goes back to the beginning and forces the user to write elloH
instead of Hello
.
I made an example of my code on Snack, the problem will be clearer when running: https://snack.expo.dev/Vv6lNzUCU
How can this be fixed?
CodePudding user response:
I tried to follow your example but couldn't come up with all the things you're doing. So I made a new snack. It necessarily doesn't answer your question, but that is because you haven't elaborated all the reasons behind that.
What this does, is adding a custom placeholder to be seen when there's no text inside TextInput
. And when you add some text, the placeholder will disappear.
Since you're trying to display the contents of written content, I made an assumption (sorry) that you're trying to build some kind of RTE kind of solution. Hence, I took your example and added the hook to highlight text content. So, try highlightedKeywords
array for that.
Here is the complete solution to be tested: https://snack.expo.dev/@zvona/manipulation-textinput-selection
And here is the code in case Expo loses their snacks:
import React from 'react';
import { StyleSheet, View, TextInput, Text } from 'react-native';
const highlightedKeywords = ['beep', 'boop'];
const App = () => {
const [inputText, setInputText] = React.useState('');
const highlightContent = () => {
const splitText = inputText.split(' ');
return splitText.map((str) => {
if (highlightedKeywords.includes(str)) {
return <Text style={[styles.overlapText, styles.highlightedText]}>{str}</Text>;
} else {
return <Text style={styles.overlapText}>{str}</Text>;
}
});
};
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput style={styles.textInput} onChangeText={setInputText} />
<View style={styles.placeholder}>
{inputText.length ? (
<><Text>{highlightContent()}</Text></>
) : (
<>
<Text>This is my </Text>
<Text style={{ backgroundColor: 'yellow' }}>Placeholder</Text>
</>
)}
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
padding: 20,
},
inputContainer: {
position: 'relative',
width: '100%',
height: 35,
},
textInput: {
zIndex: 2,
borderColor: '#202020',
borderWidth: 2,
height: '100%',
padding: 5,
color: 'transparent',
},
placeholder: {
zIndex: 0,
position: 'absolute',
display: 'block',
height: '100%',
left: 7,
top: 8,
},
overlapText: {
marginRight: '0.25em',
},
highlightedText: {
backgroundColor: '#6699CC',
color: '#ffffff',
},
});
export default App;
CodePudding user response:
I used Samuli Hakoniemi's idea of opacity
and zIndex
, but I think I simplified the code a bit:
import React from 'react';
import {
StyleSheet,
View,
TextInput,
Text
} from 'react-native';
export default function App() {
const [TEXT, setText] = React.useState(null);
return (
<View style={{ marginTop: 100, padding: 20 }}>
<View>
<TextInput
style={{
padding: 5,
borderWidth: 1,
zIndex: 1,
}}
autoFocus={true}
onChangeText={(text) => {
setText(text);
}}
value={TEXT}
/>
<View style={{
position: 'absolute',
justifyContent: 'center',
left: 5,
height: '100%',
zIndex: 0,
opacity: (TEXT) ? 0 : 1,
}}>
<Text>
<Text>My </Text>
<Text style={{ backgroundColor: 'yellow' }}>Example</Text>
</Text>
</View>
</View>
</View>
);
}
Example in Snack: https://snack.expo.dev/mOuNbvxCU