I am trying to center a text input with a width that is the length of the text input. However when I use alignSelf: 'center', or alignItems: 'center', the text input is not visible without a width.
For example:
render() {
return <View style={{flex: 1}}>
<TextInput style={{alignSelf: 'center', minWidth: 1}}>
<View/>
}
Here the minWidth ensures that the textInput can be seen but it does not expand when you type in it. And without a width / minWidth the textInput would not be seen unless the centering style was removed.
Example with almost workable workaround:
constructor(props) {
super(props)
this.state = {
txt: ""
txtWidth: 0
}
}
render() {
return <View style={{flex: 1}}>
<TextInput
style={{minWidth: 1, alignSelf: 'center', width: this.state.txtWidth}}
value={this.state.txt}
onChange={txt=>this.setState({txt: txt.nativeEvent.text})}
/>
<Text
style={{position: 'absolute', right: 100000}}
onLayout={e=>this.setState({txtWidth:e.nativeEvent.layout.width})}
>
{this.state.txt}
</Text>
<View/>
}
As the text input receives input, it grows in size and works great. However, one thing prevents it from being full proof. The e.nativeEvent.layout.width value for emoji is always 20. And the actual width of the given emoji is not 20. Thus the txtWidth is no longer the correct width for the textInput and pieces of the textInput are now cut off.
Has anyone come up with a good solution for a centered text input with a dynamic width. I have been stumped on this for way too long. Would be happy to provide clarity if needed as well.
Thanks!
Sorry kept you waiting, fininally got time to finish this. Use View,Image and Text to fake TextInput.
1st step: format text when changed
you still need a TextInput.
emoji in text might look like :fire: or 🔥, I choose the later.
when text changes use regexp replace all emoji expressions to emoji character.
then you move cursor it will not stop inside an emoji
2nd setp: faked TextInput
it should look like
<View style={{flexDirection: 'row', flexWrap: 'wrap'}}>
<Image style={styles.img} source={{uri: some_emoji}} />
<Text>
{"s"}
</Text>
<Text>
{"s"}
</Text>
<MyCursor />
</View>
the emoji images should be within the same width, and to get width of Text might look like
<Text onLayout={(event) => {
var {x, y, width, height} = event.nativeEvent.layout;
}} />
then you can get the total length and resize your View and hide your real TextInput and manage cursor, It worked in the web though not that smooth.
this is why i use Text for every char like <Text>{"s"}</Text> cursor index should change when you click on each of them, and when focus, blur and keypress happens. you may refer https://github.com/postor/react-input-emoji/blob/master/pages/index.js for a web version fake input I've tried, yet cut, paste and lot's of things remain unhandled
Related
I want to do a line like this one, but I don't know how (btw the text on the image is in spanish, but it does not matter).
You can draw a separator with flexbox properties even with a text or view or anything you want in the center of the line.
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{textAlign: 'center', paddingHorizontal:8}}>Hello</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
</View>
Pls, take a look at this link.
Hope it will help.
Draw horizontal rule in React Native
It can be done easily by installing packages.
https://daisyui.com/components/divider/
It can be done easily without adding any library. Here's an exmaple -
https://snack.expo.dev/#arjunshukla97/divider
In my app keyboard covers only bottom part of the text input. I have tried several ways to solve this by changing styles by adding padding or margin, and also KeyboardAvoidingView didn't help.
Another problem is that keyboard shifts the whole screen and header becomes invisible as it goes above.
Edit: It works fine on IOS devices.
How can I fix these problems?
Thanks
Code:
<>
<CustomHeader title={item.title}
leftChild={<SvgImageComp name={MENU_ICON}/>}
centerChild={
<TextComp text={'Title'} style={compStyle.title}/>
}
/>
<View style={{
flex: 1,
justifyContent: 'flex-end'
}}>
<KeyboardAvoidingView
behavior={"height"}
>
<TextInputComp fontFamily={NUNITO_SANS_REGULAR}
fontSize={15}
lineHeight={20}
autoFocus={true}
style={{
paddingVertical: 10,
paddingHorizontal: 20,
borderWidth: 1,
borderColor: '#000',
borderRadius: 200,
}}
/>
</KeyboardAvoidingView>
</View>
</>
For Android you don't need to pass behavior to KeyboardAvoidingView. For IOS you need to pass behavior="position" and keyboardVerticalOffset=[height of your input].
<KeyboardAvoidingView
{...(Platform.OS === 'ios'
? {
behavior: 'position' ,
keyboardVerticalOffset: [inputHeight], // calculate height using onLayout callback method
}
: {})}>
I avoid this issue by wrapping the screen in <ScrollView contentContainerStyle={flexGrow: 1}><ScrollView> This will make the whole screen turn into a scroll view once the keyboard opens. Allowing the box to be out of the way of the keyboard. This also has the added benefit of allowing you to scroll to other sections of the screen for reference while the keyboard stays open.
So I'm new to React (and JavaScript too for that matter). I'm creating an App using react native and currently trying to style my popup menu. (which looks like this: Popup menu image)
I want to change the style of the options (make the font size bigger and space them out and change the font color too). My code looks something like this:
<MenuProvider>
<Menu >
<MenuTrigger>
<Image
style={styles.menucontainer}
resizeMode="contain"
source={require('../assets/icon_more.png')}>
</Image>
</MenuTrigger>
<MenuOptions optionsContainerStyle={styles.optionsstyle}>
<MenuOption text= 'About' />
<MenuOption text= 'Help & Feedback'/>
<MenuOption text= 'Sign Out'/>
</MenuOptions>
</Menu>
</MenuProvider>
After checking
https://github.com/instea/react-native-popup-menu/blob/master/src/MenuOption.js
I found a prop customStyles. Just like I passed a styling object for MenuOptions as prop optionContainerStyle, I tried passing customStyles for MenuOption but that produced an error:
In this environment the sources for assign MUST be an object. This error is a performance optimization and not spec compliant.
Here is my styles code:
const styles = StyleSheet.create({
optionsstyle:{
marginTop: height*32/dev_dimension.h,
marginLeft: width*184/dev_dimension.w,
backgroundColor: '#fafafa',
width: width*168/dev_dimension.w,
height: height*160/dev_dimension.h,
flexDirection: 'row',
flex: 1,
justifyContent: 'space-between',
},
});
Can anyone tell what I'm doing wrong?
According to documentation the optionsContainerStyle are deprecated and I am not sure if they work properly. Try to use customStyles props instead as seen in StylingExample where you can find full example.
The thing is that customStyles is map of styles for different parts. Something like
<MenuOptions customStyles={{optionWrapper: { padding: 5}, optionText: styles.text}}>
I use the keyboardAvoidingView, to display inputs and used next focus. But, when i click in first input ( print label 1623 - Acidez ), this is hidden. How make show this?
<ReactNative.View key={this.state.selectedTabIndex}>
<ReactNative.ScrollView style={{ height: this.props.styles.height - 40 }}>
<ReactNative.KeyboardAvoidingView
keyboardVerticalOffset={0}
behavior="position"
contentContainerStyle={{ paddingTop: this.state.size }}
>
{this.tabs[this.state.selectedTabIndex].render()}
</ReactNative.KeyboardAvoidingView>
</ReactNative.ScrollView>
</ReactNative.View>
if you increase 'keyboardVerticalOffset' to bigger value like '100' of KeyboardAvoidingView to some bigger amount it would scroll up from keyboard thus avoiding it.I also spent much time in finding the right solution on internet but finally figure it out myself for 'react-native' version '0.50.4'.I got it working like this
<View style={…..}>
<ScrollView>
<KeyboardAvoidingView style={{ flex: 1 }}
keyboardVerticalOffset={100} behavior={"position"}>
</KeyboardAvoidingView>
</ScrollView>
</View>
keyboardVerticalOffset should be the distance between the top of the screen and the top of the KeyboardAvoidingView. If you're using flex, that number is going to be different depending on the size of the device you're viewing the app on.
The simplest approach I have found is to simply wrap the whole page with KeyboardAvoidingView. By making it your top-level wrapper, you will never have to worry about the keyboardVerticalOffset.
Experiment with the three behavior options from there until you get something that works.
What works today for me - on android - was..
<KeyboardAvoidingView
key={2}
keyboardVerticalOffset={0}
behavior={"padding"}
style={{
flex: 1,
overflow: "hidden",
height: "100%",
paddingTop: 0,
marginTop: 0,
borderTopWidth: 0,
}}
windowSize={1}
enabled
>
(...)
</KeyboardAvoidingView>
I am trying to create a view with a border around it that is centered and fills 80% of the screen. I have come up with this:
<View style={{flexDirection: 'row'}}>
<View style={{flex: .1}} />
<View style={{flex: .8, borderWidth: 2}} />
<View style={{flex: .1}} />
</View>
which works, but seems awfully verbose.
Is there a better (more succinct) way to create a view that is a certain percentage of the screen width and centered in the page?
UPDATE:
Starting from React Native version 0.42 we now have a full percentage support for width, height , padding and so on, see the full list and examples here:
https://github.com/facebook/react-native/commit/3f49e743bea730907066677c7cbfbb1260677d11
Old method:
Consider using Dimensions, like:
import Dimensions from 'Dimensions';
and then in element's style:
width: Dimensions.get('window').width / 100 * 80,
Working example: https://rnplay.org/apps/4pdwlg