Can I pass a Stylesheet and custom prop in the same component? - react-native

This is what I have currently and it works fine:
<View style = {styles.text}>
<Text style = {{color: colors.text}}> hello this is a sample image with text</Text>
</View>
I am using dark mode, so I added a const {colors} = useTheme(); to the top of my file. However, I cannot call that custom color prop inside a stylesheet like:
text: {
marginBottom: 15,
fontWeight: 'bold',
fontSize: 20,
**color: colors.text**
},
Dark mode won't work this way.
I am sure there is a fix for this, which I will look into into the future.
For now, my current question is: can I pass a Stylesheet and a custom styling option into the same component?
<View>
<Text style = {styles.text} && {{color: colors.text}}> hello this is a sample image with text</Text>
</View>
for example

You can use
<Text style={[styles.text, {color: colors.text}]}>Sample</Text>;
or
<Text style={{...styles.text, color: colors.text}}>Sample</Text>

Related

Handle on press in a react-native custom component

I'm using react-native. I need to show a menu that consists of a list of items. I simplified the code below and I'm showing only a text but in the real case, the item has got a checkbox an icon and a label so for this reason I created a custom component.
I need to handle the on click on the items.
The problem is that the on press on the TouchableOpacity in the widget is not triggered.
If I use the same hierarchy of components directly the on click works.
So in the example below the onClick on the TouchableOpacity that is directly put in the containing view is triggered but the onClick on the TouchableOpacity that is wrapped in the EventOnMapMenuWidget is not triggered.
How can I handle the onClick on the TouchableOpacity in the EventOnMapMenuWidget?
Please notice that in the log I don't see the
EventOnMapMenuWidget onPress
while I see the
TEST onPress
private drawEventsOnMapForm() {
return <View style={{ margin: marginStyle.medium, flexDirection: 'column' }}>
<EventOnMapMenuWidget
onToggle={() => {
console.log("EventOnMapMenuWidget onToggle")
}}
label={STRINGS.speeding}
/>
<TouchableOpacity style={{ margin: marginStyle.medium, flexDirection: 'row' }} onPress={() => {
console.log("TEST onPress")
}}>
<Text style={{ color: COLORS.black }}>{STRINGS.speeding}</Text>
</TouchableOpacity>
</View>
}
This is the definition of the custom components:
export default class EventOnMapMenuWidget extends Component<EventOnMapMenuWidgetProp> {
render() {
return <TouchableOpacity style={{ margin: marginStyle.medium, flexDirection: 'row' }} onPress={()=> {
console.log("EventOnMapMenuWidget onPress", this.props.label)
this.props.onToggle()
}}>
<Text style={{color: COLORS.black}}>{this.props.label}</Text>
</TouchableOpacity>
}
}

How to change button fontSize in React Native?

How can I change the following button's font size? Using the style attribute with fontSize doesn't work.
<Button
style={{fontSize: 32}}
uppercase={false}
mode="contained">
Some text
</Button>
The React Native Button is very limited in what you can do, see; https://facebook.github.io/react-native/docs/button
It does not have a style prop, and you don't set fontSize.
If you want to have more control over the appearance you should use one of the TouchableXXXX' components like TouchableOpacity They are really easy to use :-)
I have make a button for you . hope it will useful for you
<TouchableOpacity style={{height:50,backgroundColor:"skyblue",alignItems:'center',justifyContent:'center'}}>
<Text style={{fontSize:32,}}>Some Text</Text>
</TouchableOpacity>
I use the Text component inside TouchableXXX for every button, it's more flexible and works fine, you can also try to make you own button component and passing props that you want to control (fontsize, colors ...):
<TouchableHighlight onPress={handelPress} style={styles.buttonStyle}>
<Text style={styles.buttonTextStyle}>Click here</Text>
</TouchableHighlight>
If you are using 'react-native-elements' button, use titleStyle to set font size.
import {Input, Button} from 'react-native-elements';
<Button
titleStyle={{
color: "white",
fontSize: 16,
}}
buttonStyle={{
backgroundColor: "white",
borderRadius: 60,
flex: 1,
}}
title="Click here"
/>
For React-native Button, you can use use TouchableOpacity.
<TouchableOpacity style={{height:50}}>
<Text style={{fontSize:36}}>Click here</Text>
</TouchableOpacity>

How to make an image of a <ImageBackground> tag darker (React Native)

I'm trying to create an image with a text on it, and in order for the the text to be clearly seen I need to make the image darker.
Also (don't sure if it matters or not) I need the background image to be touchable.
This question was asked several times here and I've seen some answers, but none of them worked for me, so I'm wondering if I'm missing something more crucial here.
My code is the following:
<View style={postStyles.container}>
<TouchableOpacity onPress={() =>
this.props.navigation.navigate('AnotherWindow')}>
<ImageBackground source={require('../../assets/images/my_img.jpg')}
style={{width: '100%', height: 150}}>
<Text style={postStyles.title} numberOfLines={2}>
My text
</Text>
</ImageBackground></TouchableOpacity>
From looking around here, I've tried the following solutions:
Tried to wrap the text element inside the imagebackground tag inside a
View element that has a style property of "backgroundColor" with value of 'rgba(255,0,0,0.5)' (also tried different values),
Tried to add this backgroundColor property to the styles of both the container itself, the TouchableOpacity element
Tried to above two solutions with the "elevation" property instead of backgroundColor (I work in Android).
None of the above solutions worked, in a sense that the background image didn't change at all, so I'm wondering if I'm missing something more crucial.
Thanks!
If anyone still having problems with the ImageBackground component, this is how i solved it, basically i set a view inside the image background which has the backgroundColor that darkens the image.
<ImageBackground
source={Images.background}
style={styles.imageBackground}
>
<View style={styles.innerContainer}>
{content}
</View>
</ImageBackground>
const styles = StyleSheet.create({
imageBackground: {
height: '100%',
width: '100%'
},
innerContainer: {
flex: 1,
backgroundColor: 'rgba(0,0,0, 0.60)'
},
});
if you want to make the image darker, you'll need the Image component and use the tintColor prop like:
<Image source={require('./your_image.png')} style={{ tintColor: 'cyan' }}>
this tintColor prop only works for Image component not ImageBackground, also if you want to add a text on the Image component, you'll need to positioning that text with position: 'absolute' or 'relative'
<View style={postStyles.container}>
<TouchableOpacity
onPress={() => his.props.navigation.navigate('AnotherWindow')}>}
>
<Image
source={require('./my_image.png')}
resizeMode="contain"
style={{ width: '100%', height: 150, tintColor: 'cyan' }}
/>
<Text style={postStyles.title} numberOfLines={2}>
My text
</Text>
</TouchableOpacity>
</View>
Also, if you implement this approach you'll need to calculate the dimensions of the screen for each device, well you'll need to check this other component from react-native: https://facebook.github.io/react-native/docs/dimensions
Please, let me know if this works :D
You should just add tintColor to ImageBackground imageStyle and you're done. easy peasy!
<TouchableOpacity onPress={() => this.props.navigation.navigate('AnotherWindow')}>
<ImageBackground source={require('../../assets/images/my_img.jpg')}
style={{width: '100%', height: 150}}
imageStyle={{tintColor: 'rgba(255,0,0,0.5)'}}>
<Text style={postStyles.title} numberOfLines={2}>
My text
</Text>
</ImageBackground>
</TouchableOpacity>

React Native Button: Fit to text layout

In the Button docs from React-Native here it shows an image which says: Fit to text layout. That is what I am searching for because my button always has full width, but I want it to only be as wide as the text is. But neither in the docs nor in the button code here I can find something related to that a prop or how can it achieve. Somebody has an idea how to get it?
I suggest making your own button with TouchableOpacity and Text.
For example this is my component I often use :
export default class RoundedButton extends React.Component<Props>{
render(){
const defStyles : StyleProp<ViewStyle> = [style.button, {
backgroundColor: this.props.backgroundColor,
}, this.props.style];
if(this.props.shadow)
defStyles.push(style.shadow);
return(
<TouchableOpacity
disabled={!this.props.onPress}
onPress={() => {
if(this.props.onPress)
this.props.onPress();
}}
style={defStyles}
>
<Text style={{
color: this.props.textColor,
fontFamily: fonts.bold,
fontSize: 16
}}>{this.props.centerText}</Text>
</TouchableOpacity>
);
}
}
You can found the full gist here if you want : https://gist.github.com/Sangrene/176c1b87ad5b355e26b5c6aa80b96eae.
You can pass the prop adjustsFontSizeToFit={true} in your Text component.
If you add a fontSize in the styles of the Text, it will override this prop and won't work.
Example
<View style={{widht: 100, height: 60}}>
<Text adjustsFontSizeToFit={true}>
Your Text Here
</Text>
</View>

Disabling buttons on react native

I'm making an android app using react native and I've used TouchableOpacity component to create buttons.
I use a text input component to accept text from the user and the button should only be enabled once the text input matches a certain string.
I can think of a way to do this by initially rendering the button without the TouchableOpactiy wrapper and re-rendering with the wrapper once the input string matches.
But I'm guessing there is a much better way to do this. Can anyone help?
TouchableOpacity extends TouchableWithoutFeedback, so you can just use the disabled property :
<TouchableOpacity disabled={true}>
<Text>I'm disabled</Text>
</TouchableOpacity>
React Native TouchableWithoutFeedback #disabled documentation
The new Pressable API has a disabled option too :
<Pressable disabled={true}>
{({ pressed }) => (
<Text>I'm disabled</Text>
)}
</Pressable>
Just do this
<TouchableOpacity activeOpacity={disabled ? 1 : 0.7} onPress={!disabled && onPress}>
<View>
<Text>{text}</Text>
</View>
</TouchableOpacity>
this native-base there is solution:
<Button
block
disabled={!learnedWordsByUser.length}
style={{ marginTop: 10 }}
onPress={learnedWordsByUser.length && () => {
onFlipCardsGenerateNewWords(learnedWordsByUser)
onFlipCardsBtnPress()
}}
>
<Text>Let's Review</Text>
</Button>
So it is very easy to disable any button in react native
<TouchableOpacity disabled={true}>
<Text>
This is disabled button
</Text>
</TouchableOpacity>
disabled is a prop in react native and when you set its value to "true" it will disable your button
Happy Cooding
This seems like the kind of thing that could be solved using a Higher Order Component. I could be wrong though because I'm struggling to understand it 100% myself, but maybe it'll be helpful to you (here's a couple links)...
http://www.bennadel.com/blog/2888-experimenting-with-higher-order-components-in-reactjs.htm
http://jamesknelson.com/structuring-react-applications-higher-order-components/
TouchableOpacity receives activeOpacity. You can do something like this
<TouchableOpacity activeOpacity={enabled ? 0.5 : 1}>
</TouchableOpacity>
So if it's enabled, it will look normal, otherwise, it will look just like touchablewithoutfeedback.
To disable Text you have to set the opacity:0 in Text style like this:
<TouchableOpacity style={{opacity:0}}>
<Text>I'm disabled</Text>
</TouchableOpacity>
You can use the disabled prop in TouchableOpacity when your input does not match the string
<TouchableOpacity disabled = { stringMatched ? false : true }>
<Text>Some Text</Text>
</TouchableOpacity>
where stringMatched is a state.
You can build an CustButton with TouchableWithoutFeedback, and set the effect and logic you want with onPressIn, onPressout or other props.
I was able to fix this by putting a conditional in the style property.
const startQuizDisabled = () => props.deck.cards.length === 0;
<TouchableOpacity
style={startQuizDisabled() ? styles.androidStartQuizDisable : styles.androidStartQuiz}
onPress={startQuiz}
disabled={startQuizDisabled()}
>
<Text
style={styles.androidStartQuizBtn}
>Start Quiz</Text>
</TouchableOpacity>
const styles = StyleSheet.create({
androidStartQuiz: {
marginTop:25,
backgroundColor: "green",
padding: 10,
borderRadius: 5,
borderWidth: 1
},
androidStartQuizDisable: {
marginTop:25,
backgroundColor: "green",
padding: 10,
borderRadius: 5,
borderWidth: 1,
opacity: 0.4
},
androidStartQuizBtn: {
color: "white",
fontSize: 24
}
})
I think the most efficient way is to wrap the touchableOpacity with a view and add the prop pointerEvents with a style condition.
<View style={this.state.disabled && commonStyles.buttonDisabled}
pointerEvents={this.state.disabled ? "none" : "auto"}>
<TouchableOpacity
style={styles.connectButton}>
<Text style={styles.connectButtonText}">CONNECT </Text>
</TouchableOpacity>
</View>
CSS:
buttonDisabled: {
opacity: 0.7
}
Here's my work around for this I hope it helps :
<TouchableOpacity
onPress={() => {
this.onSubmit()
}}
disabled={this.state.validity}
style={this.state.validity ?
SignUpStyleSheet.inputStyle :
[SignUpStyleSheet.inputAndButton, {opacity: 0.5}]}>
<Text style={SignUpStyleSheet.buttonsText}>Sign-Up</Text>
</TouchableOpacity>
in SignUpStyleSheet.inputStyle holds the style for the button when it disabled or not, then in style={this.state.validity ? SignUpStyleSheet.inputStyle : [SignUpStyleSheet.inputAndButton, {opacity: 0.5}]} I add the opacity property if the button is disabled.
You can enable and disable button or by using condition or directly by default it will be disable : true
// in calling function of button
handledisableenable()
{
// set the state for disabling or enabling the button
if(ifSomeConditionReturnsTrue)
{
this.setState({ Isbuttonenable : true })
}
else
{
this.setState({ Isbuttonenable : false})
}
}
<TouchableOpacity onPress ={this.handledisableenable} disabled=
{this.state.Isbuttonenable}>
<Text> Button </Text>
</TouchableOpacity>
Use disabled true property
<TouchableOpacity disabled={true}> </TouchableOpacity>
Here is the simplest solution ever:
You can add onPressOut event to the TouchableOpcaity
and do whatever you want to do.
It will not let user to press again until onPressOut is done